MySQL查询:按tc.sno去重并获取最新日期的记录
解决MySQL查询每个唯一
tc.sno最新日期行的问题 我明白你的需求了——你需要从当前的关联查询结果中,针对每个唯一的tc.sno,只保留对应st.date最新的那一行数据,对吧?下面给你两种常用的解决方案,适配不同版本的MySQL:
方法一:使用窗口函数(MySQL 8.0+ 推荐)
窗口函数是处理这类“分组取Top1”场景最简洁高效的方式,我们可以用ROW_NUMBER()给每个tc.sno分组内的行按日期倒序编号,然后只取编号为1的行:
WITH ranked_data AS ( SELECT st.seno, tc.pl, tc.sno, st.val1, st.val2, st.date, -- 按tc.sno分组,每行按st.date降序生成序号 ROW_NUMBER() OVER (PARTITION BY tc.sno ORDER BY st.date DESC) AS rn FROM tc LEFT JOIN st ON tc.seno = st.seno AND tc.pl = st.pl AND st.seno = 1304239136 WHERE tc.pl = 1 ) SELECT seno, pl, sno, val1, val2, date FROM ranked_data WHERE rn = 1; -- 只保留每个sno的最新行
逻辑说明:
PARTITION BY tc.sno:把数据按tc.sno分成不同的组ORDER BY st.date DESC:每个组内按日期从新到旧排序ROW_NUMBER():给每个组内的行依次编号,最新的那行编号为1- 外层查询筛选
rn=1,就能得到每个tc.sno的最新数据行
方法二:兼容MySQL 5.x版本(无窗口函数)
如果你的MySQL版本低于8.0,不支持窗口函数,可以用子查询先找到每个tc.sno对应的最大日期,再关联原查询获取完整数据:
SELECT st.seno, tc.pl, tc.sno, st.val1, st.val2, st.date FROM tc LEFT JOIN st ON tc.seno = st.seno AND tc.pl = st.pl AND st.seno = 1304239136 WHERE tc.pl = 1 AND (tc.sno, st.date) IN ( -- 子查询:找到每个tc.sno对应的最大st.date SELECT tc_inner.sno, MAX(st_inner.date) FROM tc tc_inner LEFT JOIN st st_inner ON tc_inner.seno = st_inner.seno AND tc_inner.pl = st_inner.pl AND st_inner.seno = 1304239136 WHERE tc_inner.pl = 1 GROUP BY tc_inner.sno );
额外注意:
- 如果某个
tc.sno对应的st.date为NULL(也就是左连接后没有匹配到st表的数据),MAX(st.date)会返回NULL,这条数据也会被保留,和你原语句的左连接逻辑一致 - 如果同一个
tc.sno有多个行的st.date完全相同,方法一的ROW_NUMBER()会随机选一行;要是想保留所有同日期的行,可以把ROW_NUMBER()换成RANK()
这样就能精准得到每个唯一tc.sno的最新日期行啦!
内容的提问来源于stack exchange,提问作者user4564280
相关产品推荐
相关产品推荐

