phpMyAdmin中MySQL/MariaDB GROUP BY不生效问题求助
解决有轨电车站点数据按站点整合时间的问题
嘿,我完全懂你现在的处境——本来想用CASE语句配合GROUP BY把同一个站点的蓝、黄、紫三种电车的抵达时间都整合到一行里,结果出来的结果却不是你想要的样子对吧?
这种情况大概率是因为你的查询里没有给CASE语句搭配合适的聚合函数,单纯用GROUP BY的话,数据库没办法确定要返回同站点下哪种颜色电车的哪条时间记录,所以会返回每组里的第一条或者随机值,自然不符合预期。
先看错误示例(大概率是你现在的写法)
假设你的原始表结构是这样的:
CREATE TABLE tram_schedules ( station_name VARCHAR(50), tram_color VARCHAR(10), arrival_time TIME );
如果你的查询是这样写的:
SELECT station_name, CASE WHEN tram_color = '蓝' THEN arrival_time END AS blue_time, CASE WHEN tram_color = '黄' THEN arrival_time END AS yellow_time, CASE WHEN tram_color = '紫' THEN arrival_time END AS purple_time FROM tram_schedules GROUP BY station_name;
那结果肯定不对,因为CASE返回的是单条记录的时间,GROUP BY后没有聚合规则,数据库不知道该保留哪个值。
正确的写法:给CASE搭配聚合函数
如果每个站点每种颜色的电车只有一条抵达时间记录,那用MAX或者MIN就能完美解决(因为它们会忽略CASE返回的NULL值,只保留对应颜色的时间):
SELECT station_name, MAX(CASE WHEN tram_color = '蓝' THEN arrival_time END) AS blue_tram_arrival, MAX(CASE WHEN tram_color = '黄' THEN arrival_time END) AS yellow_tram_arrival, MAX(CASE WHEN tram_color = '紫' THEN arrival_time END) AS purple_tram_arrival FROM tram_schedules GROUP BY station_name;
这样每个站点的一行数据里,就会分别显示三种颜色电车的抵达时间,没有的话会显示NULL。
如果同站点同颜色有多个抵达时间?
要是某站点的同一种颜色电车有多个班次,你想把所有时间都列出来,那就要用字符串拼接的聚合函数,不同数据库的函数不一样:
- PostgreSQL用
STRING_AGG:
SELECT station_name, STRING_AGG(CASE WHEN tram_color = '蓝' THEN arrival_time::TEXT END, ', ') AS blue_tram_times, STRING_AGG(CASE WHEN tram_color = '黄' THEN arrival_time::TEXT END, ', ') AS yellow_tram_times, STRING_AGG(CASE WHEN tram_color = '紫' THEN arrival_time::TEXT END, ', ') AS purple_tram_times FROM tram_schedules GROUP BY station_name;
- MySQL用
GROUP_CONCAT:
SELECT station_name, GROUP_CONCAT(CASE WHEN tram_color = '蓝' THEN arrival_time END SEPARATOR ', ') AS blue_tram_times, GROUP_CONCAT(CASE WHEN tram_color = '黄' THEN arrival_time END SEPARATOR ', ') AS yellow_tram_times, GROUP_CONCAT(CASE WHEN tram_color = '紫' THEN arrival_time END SEPARATOR ', ') AS purple_tram_times FROM tram_schedules GROUP BY station_name;
- SQL Server也用
STRING_AGG:
SELECT station_name, STRING_AGG(CASE WHEN tram_color = '蓝' THEN CONVERT(VARCHAR, arrival_time) END, ', ') AS blue_tram_times, STRING_AGG(CASE WHEN tram_color = '黄' THEN CONVERT(VARCHAR, arrival_time) END, ', ') AS yellow_tram_times, STRING_AGG(CASE WHEN tram_color = '紫' THEN CONVERT(VARCHAR, arrival_time) END, ', ') AS purple_tram_times FROM tram_schedules GROUP BY station_name;
核心思路就是:GROUP BY是用来分组的,但要把组内的对应字段值整合起来,必须配合聚合函数,CASE只是用来筛选对应颜色的时间,最终靠聚合函数把筛选后的值整合到一行里。
内容的提问来源于stack exchange,提问作者aminur rahman
相关产品推荐
相关产品推荐

