php - 如何通过 Eloquent 中具有多对多关系的外部表中的列聚合进行分组?
问题描述
我开始为此头疼,所以我想我只是在这里发布。我有两个通过数据透视表关联的表(因为它是多对多关系)。我使用 Laravel 和 Eloquent(但对于如何使用普通 SQL 查询实现这一点的一般帮助也非常感谢)。
我想根据第二个表的列订购第一个表,但为此需要“聚合”列。
由许多司机共享并且可以有不同颜色的汽车的示例:
Car-Table: [id, color]
Driver-Table: [id, name]
Car.Driver-Table: [car_id, driver_id]
我需要一个查询来获取所有只驾驶红色汽车的司机,然后是所有不驾驶红色汽车的司机。
我必须使用查询,因为之后我可能会对此查询执行其他操作(如过滤)并希望最后分页。
我已经使用了获取两个组之一的查询。它们看起来像这样: 在 Driver 模型中:
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
只允许表格的一列作为第二个参数。是否有另一种方法可以从有序联合查询中以正确的顺序获取模型?
解决方案
这是我得到的最好的:
$driversWithOnlyRedCars = Driver::whereHas('cars',function($q){
$q->where('color', 'red');
})->withCount('cars')->get()->where('cars_count',1);
推荐阅读
- python - 使用基于excel文件的python代码同步到JIRA
- javascript - 尽管 CSS 在开发工具中似乎是正确的,但无法找到元素(量角器 Jasva 脚本)
- javascript - 如何在Javascript中仅获取DOM元素中直接包含的文本?
- python - tensorflow 过渡到 gpu 版本
- android - 如何在 React Native 中使用多个目标
- centos - 是否可以就地升级 CentOS 7 到 8
- graphql - Apollo GraphQl 分页 - 限制和跳过
- pytorch - 在 PyTorch 中提取子张量
- java - Apache POI (.xlsx) - 空值 - 我希望忽略一些而使用其他的(例如,检查是否填写了必填字段)
- networking - 如何在 Chrome 开发者工具中延迟资源加载