在具有关系的 Laravel Eloquent 查询构建器中将 UNION 与 DISTINCT 结合使用
Use UNION with DISTINCT in Laravel Eloquent query builder with relations
我有 2 个 table,
properties
+----+-----------+
| id | parent_id |
+----+-----------+
| 1 | null |
| 2 | 1 |
| 3 | null |
| 4 | 3 |
| 5 | 3 |
| 6 | null |
+----+-----------+
和
sale_services
+----+-------------+------+
| id | property_id | rank |
+----+-------------+------+
| 1 | 2 | 5 |
| 2 | 4 | 4 |
| 3 | 5 | 6 |
| 4 | 6 | 7 |
+----+-------------+------+
通过关系 (sale_service.property_id = property.id)。 属性 可以链接到同一个 属性 中的另一个 table.
我需要获取 SaleService 实例的集合,其中相关的 property.parent_id
为 null 或者 sale_services
[=78= 中有一些记录] 通过 properties
table 共享相同的 parent_id
,按该字段区分并按 rank
.
排序
结果应该是
+----+-------------+------+
| id | property_id | rank |
+----+-------------+------+
| 1 | 2 | 5 |
| 3 | 5 | 6 |
| 4 | 6 | 7 |
+----+-------------+------+
- sale_services
table 中的所有项目,除了 (sale_service.id = 2),因为它 属性 共享相同的 parent_id
与项目 (sale_service.id = 3) 和项目与 (sale_service.id = 3) 最高 rank
价值
我找到了 SQL 代码来获得想要的结果,
SELECT *
FROM
(SELECT DISTINCT ON (properties.parent_id) *
FROM "sale_services"
INNER JOIN "properties" ON "sale_services"."property_id" = "properties"."id"
WHERE ("properties"."parent_id") IS NOT NULL
ORDER BY "properties"."parent_id", "sale_services"."rank" DESC) AS sub
UNION
SELECT *
FROM "sale_services"
INNER JOIN "properties" ON "sale_services"."property_id" = "properties"."id"
WHERE ("properties"."parent_id") IS NULL
但我无法与 Eloquent Builder 达到相同的水平。
我试过这样的东西
$queryWithParent = SaleService::query()
->select(\DB::raw('DISTINCT ON (properties.parent_id) *'))
->whereNotNull('properties.parent_id')
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->orderBy('parent_id')
->orderBy('sale_services.index_range', 'desc');
$queryWithoutParent = SaleService::query()
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->whereNull('properties.parent_id');
$query = $queryWithParent->union($queryWithoutParent);
但出现错误
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "union" LINE 1: ...perties.type <> 'hotel') order by "parent_id" asc union sele... ^ (SQL: select DISTINCT ON (properties.parent_id) * from "sale_services" inner join "properties" on "sale_services"."property_id" = "properties"."id" where ("properties"."parent_id") is not null and ("sale_services"."deleted_at") is null and "published" = 1 and exists (select 1 from "properties" where properties.id = sale_services.property_id AND properties.type <> 'hotel') order by "parent_id" asc union select * from "sale_services" inner join "properties" on "sale_services"."property_id" = "properties"."id" where ("properties"."parent_id") is null and ("sale_services"."deleted_at") is null and "published" = 1 and exists (select 1 from "properties" where properties.id = sale_services.property_id AND properties.type <> 'hotel') order by "index_range" desc limit 12 offset 0)
如果我从第一个查询中删除排序 ($queryWithParent) 它似乎有效,但在不同的查询中选择了随机项目。
是否有任何其他方法可以达到相同的结果,或者我做错了什么?
"Distinct" 的 laravel 查询创建者是 distinct(),如:
$queryWithParent = SaleService::query()
->distinct('properties.parent_id')
->whereNotNull('properties.parent_id')
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->orderBy('parent_id')
->orderBy('sale_services.index_range', 'desc');
这样行吗?
终于找到解决办法了。
- 使用Laravel ^5.7.28(UNION 问题已在Laravel 5.7.28: github.com/laravel/framework/pull/27589 中修复),您将不需要子查询!
将table列指定为select以避免列名冲突sale_services.*
$queryWithParent = SaleService::query()
->select(\DB::raw('DISTINCT ON (properties.parent_id) sale_services.*'))
->from('sale_services')
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->whereNotNull('properties.parent_id')
->orderBy('properties.parent_id')
->orderBy('sale_services.index_range', 'desc');
$queryWithoutParent = SaleService::query()
->select(\DB::raw('sale_services.*'))
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->whereNull('properties.parent_id');
$query = $queryWithParent->union($queryWithoutParent);
我有 2 个 table,
properties
+----+-----------+
| id | parent_id |
+----+-----------+
| 1 | null |
| 2 | 1 |
| 3 | null |
| 4 | 3 |
| 5 | 3 |
| 6 | null |
+----+-----------+
和
sale_services
+----+-------------+------+
| id | property_id | rank |
+----+-------------+------+
| 1 | 2 | 5 |
| 2 | 4 | 4 |
| 3 | 5 | 6 |
| 4 | 6 | 7 |
+----+-------------+------+
通过关系 (sale_service.property_id = property.id)。 属性 可以链接到同一个 属性 中的另一个 table.
我需要获取 SaleService 实例的集合,其中相关的 property.parent_id
为 null 或者 sale_services
[=78= 中有一些记录] 通过 properties
table 共享相同的 parent_id
,按该字段区分并按 rank
.
结果应该是
+----+-------------+------+
| id | property_id | rank |
+----+-------------+------+
| 1 | 2 | 5 |
| 3 | 5 | 6 |
| 4 | 6 | 7 |
+----+-------------+------+
- sale_services
table 中的所有项目,除了 (sale_service.id = 2),因为它 属性 共享相同的 parent_id
与项目 (sale_service.id = 3) 和项目与 (sale_service.id = 3) 最高 rank
价值
我找到了 SQL 代码来获得想要的结果,
SELECT *
FROM
(SELECT DISTINCT ON (properties.parent_id) *
FROM "sale_services"
INNER JOIN "properties" ON "sale_services"."property_id" = "properties"."id"
WHERE ("properties"."parent_id") IS NOT NULL
ORDER BY "properties"."parent_id", "sale_services"."rank" DESC) AS sub
UNION
SELECT *
FROM "sale_services"
INNER JOIN "properties" ON "sale_services"."property_id" = "properties"."id"
WHERE ("properties"."parent_id") IS NULL
但我无法与 Eloquent Builder 达到相同的水平。
我试过这样的东西
$queryWithParent = SaleService::query()
->select(\DB::raw('DISTINCT ON (properties.parent_id) *'))
->whereNotNull('properties.parent_id')
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->orderBy('parent_id')
->orderBy('sale_services.index_range', 'desc');
$queryWithoutParent = SaleService::query()
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->whereNull('properties.parent_id');
$query = $queryWithParent->union($queryWithoutParent);
但出现错误
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "union" LINE 1: ...perties.type <> 'hotel') order by "parent_id" asc union sele... ^ (SQL: select DISTINCT ON (properties.parent_id) * from "sale_services" inner join "properties" on "sale_services"."property_id" = "properties"."id" where ("properties"."parent_id") is not null and ("sale_services"."deleted_at") is null and "published" = 1 and exists (select 1 from "properties" where properties.id = sale_services.property_id AND properties.type <> 'hotel') order by "parent_id" asc union select * from "sale_services" inner join "properties" on "sale_services"."property_id" = "properties"."id" where ("properties"."parent_id") is null and ("sale_services"."deleted_at") is null and "published" = 1 and exists (select 1 from "properties" where properties.id = sale_services.property_id AND properties.type <> 'hotel') order by "index_range" desc limit 12 offset 0)
如果我从第一个查询中删除排序 ($queryWithParent) 它似乎有效,但在不同的查询中选择了随机项目。
是否有任何其他方法可以达到相同的结果,或者我做错了什么?
"Distinct" 的 laravel 查询创建者是 distinct(),如:
$queryWithParent = SaleService::query()
->distinct('properties.parent_id')
->whereNotNull('properties.parent_id')
->join('properties', 'sale_services.property_id', '=', 'properties.id')
->orderBy('parent_id')
->orderBy('sale_services.index_range', 'desc');
这样行吗?
终于找到解决办法了。
- 使用Laravel ^5.7.28(UNION 问题已在Laravel 5.7.28: github.com/laravel/framework/pull/27589 中修复),您将不需要子查询!
将table列指定为select以避免列名冲突
sale_services.*
$queryWithParent = SaleService::query() ->select(\DB::raw('DISTINCT ON (properties.parent_id) sale_services.*')) ->from('sale_services') ->join('properties', 'sale_services.property_id', '=', 'properties.id') ->whereNotNull('properties.parent_id') ->orderBy('properties.parent_id') ->orderBy('sale_services.index_range', 'desc'); $queryWithoutParent = SaleService::query() ->select(\DB::raw('sale_services.*')) ->join('properties', 'sale_services.property_id', '=', 'properties.id') ->whereNull('properties.parent_id'); $query = $queryWithParent->union($queryWithoutParent);