为什么我的 Laravel Eloquent 查询在应用带有附加过滤器的联接后返回日期不正确的记录,尽管初始日期有限制?

问题描述 投票:0回答:1

我正在使用 Laravel Eloquent 从

views
表中获取记录,并按特定的
video_ids
created_at
日期过滤它们。我还需要连接另一个表
devices
以根据设备类型、区域和主机名应用其他过滤器。

这是我的表格的结构:

views
表:

  • id(主键)
  • 视频_id
  • device_id(外键)
  • created_at(日期时间字符串)

devices
表:

  • id(主键)
  • 类型
  • 国家
  • 主机名
  • created_at(日期时间字符串)

这是我的查询的结构:

// this is an example of what $dates looks like
// $dates = ['2024-08-01', '2024-08-02', '2024-08-03'];

public function getViews($videoIds, $dates, $devices, $regions, $sources){
    // Filter by video_id and created_at first
    $query = View::whereIn('views.video_id', $videoIds)
        ->whereIn(DB::raw('DATE(views.created_at)'), $dates);

    // Apply the join and other filters only if devices, regions, or sources are provided
    if (!empty($devices) || !empty($regions) || !empty($sources)) {
        $query->join('devices', 'devices.id', '=', 'views.device_id');

        $query->when(!empty($devices), function ($query) use ($devices) {
            return $query->whereIn('devices.types', array_map(fn($device) => $device['value'], $devices));
        });

        $query->when(!empty($regions), function ($query) use ($regions) {
            return $query->whereIn('devices.country', array_map(fn($region) => $region['value'], $regions));
        });

        $query->when(!empty($sources), function ($query) use ($sources) {
            return $query->whereIn('new_devices.hostname', array_map(fn($source) => $source['value'], $sources));
        });
    }

    return $query->get();
}

我面临的问题是,应用联接后,结果集包含带有created_at日期的视图,这些视图不在我提供的

$dates
数组中。我需要查询仅返回
created_at
日期在指定范围内的记录,即使在应用联接之后也是如此。

我的问题是:

  • 为什么连接会导致查询返回created_at日期超出指定范围的记录?
  • 如何修改我的查询,以便在应用联接后它仍然遵循日期过滤器?

我正在寻找一种解决方案,确保结果集仅包含所提供的 $dates 数组中具有created_at日期的视图,即使通过联接应用了其他过滤器也是如此。

任何帮助将不胜感激!

php laravel eloquent query-builder
1个回答
0
投票

执行

join
查询时,始终
SELECT
您需要的列。假设您有以下数据(跳过不必要的列)

浏览量

id 设备ID 创建于
1 1 2024-01-01T00:00:00

设备

id 创建于
1 2024-08-02T00:00:00

如果您执行类似的查询

SELECT * from views join devices on devices.id = views.device_id;

数据库服务器将返回一行,例如

id 设备ID 创建于 id 创建于
1 1 2024-01-01T00:00:00 1 2024-08-02T00:00:00

注意这里有两个

created_at
views.created_at
devices.created_at

当 PHP 读取它时,它将其转换为对象/数组,并且这些不能有重复的键,因此它只使用其中之一。所以它会变成以下之一

['id' => 1, 'device_id' => 1, 'created_at' => '2024-01-01T00:00:00']
['id' => 1, 'device_id' => 1, 'created_at' => '2024-08-02T00:00:00']

这可能是您遇到过的情况,您在结果中看到的

created_at
很可能来自其他表。

要解决此问题,您可以使用 select 指定要从中选择列的表

View::select('views.*', 'devices.created_at as device_created_at', /* other columns you need from devices */)
© www.soinside.com 2019 - 2024. All rights reserved.