GROUP BY分步计算需求:先取最大日期再取最大ID的SQL实现疑问
分步思路验证与SQL实现方案
思路正确性验证
你的分步思路完全合理。直接执行SELECT max(id), sale_id, max(date) FROM sales GROUP BY sale_id存在逻辑漏洞:该语句会分别取每个sale_id下的最大id和最大date,但这两个值可能来自不同的记录(比如某个sale_id里最大的id对应的日期并非该组的最大日期),导致结果不符合业务预期。
分步筛选的逻辑则能规避这个问题:先锁定每个sale_id的最大日期,再从中选取最大的id,确保最终记录是每个sale_id下最新日期对应的最大id,逻辑严谨且符合需求。
具体SQL实现
方式一:完全贴合分步思路的子查询写法
步骤1:获取每个sale_id的最大日期
SELECT sale_id, MAX(date) AS max_date FROM sales GROUP BY sale_id
步骤2:筛选出所有属于该sale_id且日期等于最大日期的记录(中间结果)
SELECT s.id, s.date, s.sale_id FROM sales s INNER JOIN ( SELECT sale_id, MAX(date) AS max_date FROM sales GROUP BY sale_id ) t ON s.sale_id = t.sale_id AND s.date = t.max_date
步骤3:从中间结果中按sale_id分组取最大id(最终结果)
SELECT MAX(id) AS id, MAX(date) AS date, sale_id FROM ( SELECT s.id, s.date, s.sale_id FROM sales s INNER JOIN ( SELECT sale_id, MAX(date) AS max_date FROM sales GROUP BY sale_id ) t ON s.sale_id = t.sale_id AND s.date = t.max_date ) temp GROUP BY sale_id
方式二:更简洁的窗口函数写法(推荐)
使用ROW_NUMBER()窗口函数可以一步到位实现需求,逻辑和分步思路完全一致:
SELECT id, date, sale_id FROM ( SELECT id, date, sale_id, -- 按sale_id分组,先按日期降序,再按id降序排序,每组第一条即为目标记录 ROW_NUMBER() OVER (PARTITION BY sale_id ORDER BY date DESC, id DESC) AS rn FROM sales ) t WHERE rn = 1
针对你的示例数据,该语句会为sale_id=5675的记录按date降序、id降序排序,id=3的记录排第1;为sale_id=5676的记录排序后,id=6的记录排第1,最终输出完全符合你的预期结果。
内容的提问来源于stack exchange,提问作者Data_Analyst
相关产品推荐
相关产品推荐

