MySQL中ORDER BY后执行GROUP BY取不到预期分组行是什么原因?
问题原因
- MySQL 优化器会自动忽略没有LIMIT的子查询中的ORDER BY语句,你在子查询中做的排序操作会被直接丢弃,并没有生效。MySQL认为子查询内部排序后不需要限制返回行数的话,排序是无意义的,所以不会执行该逻辑。
- 你的写法不符合SQL标准的GROUP BY语义,当MySQL关闭
ONLY_FULL_GROUP_BY模式时,允许SELECT 非分组列、非聚合列,此时这些列的返回值是不确定的,数据库只会随机返回分组内的某一行数据,不会保证返回排序后的第一行,所以你无论怎么调整子查询的排序方向,都无法稳定拿到预期的行。如果开启ONLY_FULL_GROUP_BY模式,你的这条SQL会直接报错。
正确实现方案
方案1:关联最小时间查询(兼容所有MySQL版本)
先通过分组查询拿到每个车辆的最早 pickup_time,再关联回原表匹配对应的完整行:
SELECT t.* FROM trips t INNER JOIN ( SELECT vehicle_id, MIN(pickup_time) AS min_pickup_time FROM trips WHERE vehicle_id IS NOT NULL GROUP BY vehicle_id ) AS min_t ON t.vehicle_id = min_t.vehicle_id AND t.pickup_time = min_t.min_pickup_time WHERE t.vehicle_id IS NOT NULL
如果同一车辆存在多个完全相同pickup_time的行程,该写法会返回所有匹配行。
方案2:窗口函数(MySQL 8.0+ 推荐)
用ROW_NUMBER()窗口函数按车辆分组后按乘车时间排序,取每个分组的第一行即可:
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY vehicle_id ORDER BY pickup_time ASC) AS group_rn FROM trips WHERE vehicle_id IS NOT NULL ) AS tmp WHERE group_rn = 1
如果同一时间的多个行程需要都返回,可将ROW_NUMBER()替换为RANK()。
内容的提问来源于stack exchange,提问作者Bing
相关产品推荐
相关产品推荐

