我对此开始感到头疼,所以我认为我只是将其发布在这里。
我有两个通过数据透视表关联的表(因为这是多对多关系)。我使用Laravel和Eloquent(但也非常感谢您通过常规SQL查询获得有关如何实现此目的的一般帮助)。
我想基于第二个表的列来排序第一个表,但是为此需要将该列“聚合”。
许多驾驶员共享并具有不同颜色的汽车的示例:
Car-Table: [id, color]
Driver-Table: [id, name]
Car.Driver-Table: [car_id, driver_id]
我需要一个查询,该查询将所有仅驾驶红色汽车的驾驶员,然后所有不驾驶红色汽车的驾驶员。
我必须使用查询,因为此后我可能会对此查询执行其他操作(例如过滤),并希望最后进行分页。
我已经使用查询来获取两组之一。他们看起来像这样:
在驱动程序模型中:
public function redCars() {
return $this->cars()->where('color', 'red');
}
public function otherColoredCars() {
return $this->cars()->where('color', '<>', 'red');
}
然后在控制器中的某个位置:
$driversWithOnlyRedCars = Driver::whereDoesntHave('otherColoredCars')->get();
$driversWithoutRedCars = Driver::whereDoesntHave('redCars')->get();
有没有办法将两者结合起来?
也许我只是在想这里完全错误。
更新进行说明:
基本上,我需要这样的东西(其他可以导致相同结果的方式)
$driversWithOnlyRedCars->addTemporaryColumn('order_column', 0); // Create temporary column with value 0
$driversWithoutRedCars->addTemporaryColumn('order_column', 1);
$combinedQuery = $driversWithOnlyRedCars->combineWith($driversWithoutRedCars); // Somehow combine both queries
$orderedQuery = $combinedQuery->orderBy('order_colum');
$results = $combinedQuery->get();
更新2
我想,我发现了如何通过原始查询实现目标。
会是这样的:
$a = DB::table(DB::raw("(
SELECT id, 0 as ordering
FROM drivers
WHERE EXISTS (
SELECT * FROM cars
LEFT JOIN driver_car ON car.id = driver_car.car_id
WHERE driver.id = driver_car.driver_id
AND cars.color = 'red'
)
) as only_red_cars"));
$b = DB::table(DB::raw("(
SELECT id, 1 as ordering
FROM drivers
WHERE EXISTS (
SELECT * FROM cars
LEFT JOIN driver_car ON car.id = driver_car.car_id
WHERE driver.id = driver_car.driver_id
AND cars.color <> 'red'
)
) as no_red_cars"));
$orderedQuery = $a->union($b)->orderBy('ordering');
现在的问题是,我需要像这样排序并最终分页的模型,所以这并不是我的问题的真正答案。我尝试将其转换回模型,但尚未成功。我尝试过的:
$queriedIds = array_column($orderedQuery->get()->toArray(), 'id');
$orderedModels = Driver::orderByRaw('(FIND_IN_SET(drivers.id, "' . implode(',', $queriedIds) . '"))');
但是看起来FIND_IN_SET
仅允许将表的列作为第二个参数。有没有其他方法可以从有序的联合查询中按正确的顺序获取模型?
答案 0 :(得分:0)
这是我得到的最好成绩:
$driversWithOnlyRedCars = Driver::whereHas('cars',function($q){
$q->where('color', 'red');
})->withCount('cars')->get()->where('cars_count',1);
答案 1 :(得分:0)
您可以使用24
53
查询:
UNION
您如何订购具有相同$driversWithOnlyRedCars = Driver::select('*', DB::raw('0 as ordering'))
->whereDoesntHave('otherColoredCars');
$driversWithoutRedCars = Driver::select('*', DB::raw('1 as ordering'))
->whereDoesntHave('redCars');
$drivers = $driversWithOnlyRedCars->union($driversWithoutRedCars)
->orderBy('ordering')
->orderBy('') // TODO
->paginate();
的驱动程序?您应该添加第二个ordering
子句,以在每次执行查询时获得一致的顺序。