在 MySQL 中使用 Case 加入 Group By & Order
Posted
技术标签:
【中文标题】在 MySQL 中使用 Case 加入 Group By & Order【英文标题】:Join with Group By & Order by using Case in MySQL 【发布时间】:2016-06-11 14:15:11 【问题描述】:为什么这个查询不起作用?是因为 order by 和 group by 的组合吗?
一个表是广告,另一个是订阅,第三个是服务,第四个是服务和位置之间的多对多关系(位置是应该显示广告的位置)。
我想要的是先订购存储在具有位置 2 的广告表中的广告,然后是那些没有定义位置的广告,然后是位置 1(此订单是通过程序生成的)
广告表:id、名称、subscription_id
订阅表:subscription_id、service_id、日期、付费等...
service_locations 表:service_id、location_id
你可以看到在这种情况下有第四张桌子,但这并不重要
查询:
select adverts.id, GROUP_CONCAT(service_locations.location_id) AS locations from adverts
left join subscriptions
on adverts.subscription_id = subscriptions.id
left join service_locations
on service_locations.service_id = subscriptions.service_id
group by adverts.id
order by case service_locations.location_id
when 2 then 1
when 1 then 3
else 2
end
预期结果:
+----+-----------+
| id | locations |
+----+-----------+
| 1 | 2 |
| 3 | 1,2 |
| 2 | null |
+----+-----------+
我实际得到的(第三行的位置为 2,但它位于 null 之后):
+----+-----------+
| id | locations |
+----+-----------+
| 1 | 2 |
| 2 | null |
| 3 | 1,2 |
+----+-----------+
【问题讨论】:
【参考方案1】:我找到了一个解决方案,order by 必须在 group by 之前执行,这不是默认行为,更多关于该行为在这里:https://***.com/a/14771322/4329156)(必须使用子查询)
所以,查询应该是这样的
select *, GROUP_CONCAT(location_id) as locations from (
select adverts.id AS id, service_locations.location_id AS location_id from adverts
left join subscriptions
on adverts.subscription_id = subscriptions.id
left join service_locations
on service_locations.service_id = subscriptions.service_id
order by case service_locations.location_id
when 2 then 1
when 1 then 3
else 2
end
) as table
group by table.id
order by case table.location_id
when 2 then 1
when 1 then 3
else 2
end
【讨论】:
【参考方案2】:当您使用group by
时,所有不在group by
中的列都应该具有聚合函数。所以,我认为你打算这样:
select a.id, GROUP_CONCAT(sl.location_id) AS locations
from adverts a left join
subscriptions s
on a.subscription_id = s.id left join
service_locations sl
on sl.service_id = s.service_id
group by a.id
order by max(case sl.location_id
when 2 then 1
when 1 then 3
else 2
end);
我不确定max()
是否是您真正需要的,但您确实需要一个聚合函数。这特别产生了问题中的输出:
order by (case min(sl.location_id)
when 2 then 1
when 1 then 2
else 3
end);
【讨论】:
以上是关于在 MySQL 中使用 Case 加入 Group By & Order的主要内容,如果未能解决你的问题,请参考以下文章
mysql中的group_concat与“case when”条件
SQLAlchemy:group_concat(case when ...)可能吗?
MySQL -- 行转列 -- GROUP_CONCAT -- MAX(CASE WHEN THEN)