SQL中使用DISTINCT与MIN()查询出错?求技术解答
问题分析
你的SQL核心问题出在分组逻辑错误:
- GROUP BY子句里包含了车手姓名(
d.forename、d.surname)和driverId,这会把同一赛道下的不同车手拆分成独立分组,最终每个分组计算的是该车手在该赛道的最快圈速,而非整个赛道的最快圈速。 DISTINCT完全多余,GROUP BY已经完成了分组去重的工作。
另外,r.year被加入分组后,同一条赛道不同年份的赛事会被视为不同分组,若你需要的是赛道本身(不区分年份)的最快圈速,这也会导致同一赛道出现多条记录。
修正方案
提供两种常用解决思路:
方法1:使用窗口函数(推荐,逻辑清晰)
用ROW_NUMBER()窗口函数按赛道分组,对圈速排序后取每条赛道的第一条记录(最快圈速):
SELECT track_name, fastest_lap_time, surname, driverId, race_year FROM ( SELECT r.name AS track_name, t.fastestlaptime AS fastest_lap_time, d.surname, d.driverId, r.year AS race_year, -- 按赛道分组,圈速升序排序(最快的排第一) ROW_NUMBER() OVER (PARTITION BY r.name ORDER BY t.fastestlaptime ASC) AS rn FROM races r INNER JOIN results t ON r.raceID = t.raceID INNER JOIN drivers d ON t.driverID = d.driverID WHERE t.fastestlaptime != '\N' ) AS ranked_laps WHERE rn = 1 -- 只取每条赛道的最快圈速记录 ORDER BY track_name;
方法2:子查询先找赛道最快圈速,再关联详情
先通过子查询算出每条赛道的最快圈速,再关联回原表获取对应的车手和年份信息:
SELECT r.name AS track_name, t.fastestlaptime AS fastest_lap_time, d.surname, d.driverId, r.year AS race_year FROM races r INNER JOIN results t ON r.raceID = t.raceID INNER JOIN drivers d ON t.driverID = d.driverID INNER JOIN ( -- 先找出每条赛道的最快圈速 SELECT r2.name, MIN(t2.fastestlaptime) AS min_lap_time FROM races r2 INNER JOIN results t2 ON r2.raceID = t2.raceID WHERE t2.fastestlaptime != '\N' GROUP BY r2.name ) AS track_min ON r.name = track_min.name AND t.fastestlaptime = track_min.min_lap_time WHERE t.fastestlaptime != '\N' ORDER BY track_name;
注意事项
- 若同一条赛道有多个车手跑出相同的最快圈速,方法1只会返回其中一条,方法2会返回所有并列最快的记录,可根据需求选择。
- 若需要区分赛道的不同年份(比如同一条赛道每年的最快圈速),只需把方法1的
PARTITION BY r.name改成PARTITION BY r.name, r.year,或方法2子查询的GROUP BY加上r2.year即可。
内容的提问来源于stack exchange,提问作者SNY
相关产品推荐
相关产品推荐

