求助:获取每辆车最后使用时间及部件工时的SQL查询优化
嘿,我完全懂你现在的处境——作为系统管理员临时要写SQL查数据,结果原语句要么只出来一辆车的信息,要么一堆重复记录,头疼得很对吧?咱们来把这个问题捋清楚,找到简单有效的解决办法。
首先,你的核心需求是:拿到每辆车在2017年12月里最后一次使用时间对应的所有部件工时数据。原查询的问题在于,你把DateRef放进了GROUP BY里,这就导致每个不同的时间点都会被单独分组,自然会返回所有历史记录,而不是只保留最后一次的。
下面给你两种实用的优化方案,选哪个都行,看你觉得哪个好理解:
方案一:用子查询先找每辆车的最后使用时间
先通过子查询找出每辆车在指定日期范围内的最新DateRef,再关联原表取出对应时间的所有部件数据:
SELECT c.CarID, c.DateRef, c.StartHours, a.SerialNumber, c.CarComponentID, c.StartHours + c.UsageHours AS TTSN FROM ComponentUsage c INNER JOIN Car a ON a.CarID = c.CarID -- 子查询:获取每辆车的最后使用时间 INNER JOIN ( SELECT CarID, MAX(DateRef) AS LastDateRef FROM ComponentUsage WHERE DateRef BETWEEN '2017-12-01' AND '2017-12-31' GROUP BY CarID ) latest ON c.CarID = latest.CarID AND c.DateRef = latest.LastDateRef WHERE c.DateRef BETWEEN '2017-12-01' AND '2017-12-31'
方案二:用窗口函数标记最新记录(更灵活)
窗口函数是SQL里处理这类“分组取最新”场景的利器,用RANK()给每辆车的记录按时间降序排名,最新的记录排名为1,最后筛选出排名1的即可:
WITH RankedUsage AS ( SELECT c.CarID, c.DateRef, c.StartHours, a.SerialNumber, c.CarComponentID, c.StartHours + c.UsageHours AS TTSN, -- 按车辆分组,日期从新到旧排名,同一时间的记录排名相同 RANK() OVER(PARTITION BY c.CarID ORDER BY c.DateRef DESC) AS UsageRank FROM ComponentUsage c INNER JOIN Car a ON a.CarID = c.CarID WHERE c.DateRef BETWEEN '2017-12-01' AND '2017-12-31' ) SELECT CarID, DateRef, StartHours, SerialNumber, CarComponentID, TTSN FROM RankedUsage WHERE UsageRank = 1
小提醒
- 如果你担心同一辆车在同一时间有多个部件记录(就像你原结果里那样),用
RANK()会保留所有同时间的记录,而如果用ROW_NUMBER()的话会给每个记录单独排号,可能只取一条,这里用RANK()更符合你的需求。 - 原查询里的
DISTINCT其实是多余的,因为GROUP BY已经会自动去重了。
这样调整后,就能精准拿到每辆车最后一次使用时间对应的所有部件工时数据啦!
内容的提问来源于stack exchange,提问作者Ylli Frroku
相关产品推荐
相关产品推荐

