按type分组获取最新创建用户的SQL查询无结果问题排查
问题原因分析
你写的SQL存在两个核心问题:
- 分组后列的合法性问题:按
type分组后,SELECT里的u.id、u.dtCreation既不是分组键,也没有用聚合函数处理。在严格的SQL模式下(比如MySQL开启ONLY_FULL_GROUP_BY),这种写法直接报错;即使宽松模式允许,数据库也会随机取分组内某一行的这两个列值,根本不是你要的目标行数据。 - HAVING子句的逻辑错误:
MAX(u.dtCreation)是分组后计算出的该组最大创建时间,而u.dtCreation是分组前单条记录的时间,分组后这个单条记录的上下文已经不存在了,两者无法匹配,所以条件永远不成立,自然返回空结果。
正确实现方法
这里提供几种靠谱的写法,任选一种即可:
方法1:子查询+关联查询
先找出每个type对应的最大创建时间,再关联原表筛选对应行:
SELECT u.id, u.dtCreation, u.type FROM users u INNER JOIN ( SELECT type, MAX(dtCreation) AS max_dt FROM users WHERE type IN ('aaa','bbb','ccc') GROUP BY type ) t ON u.type = t.type AND u.dtCreation = t.max_dt;
方法2:窗口函数(推荐,适用于支持窗口函数的数据库如MySQL 8+、PostgreSQL、SQL Server等)
用ROW_NUMBER()给每个type下的记录按创建时间倒序编号,取编号为1的行:
SELECT id, dtCreation, type FROM ( SELECT id, dtCreation, type, ROW_NUMBER() OVER (PARTITION BY type ORDER BY dtCreation DESC) AS rn FROM users WHERE type IN ('aaa','bbb','ccc') ) t WHERE rn = 1;
注:如果同一个type下有多个记录的dtCreation相同且都是最大值,ROW_NUMBER()会随机选一条;如果想保留所有同最大值的记录,把ROW_NUMBER()换成RANK()即可。
方法3:EXISTS子查询
判断当前记录的dtCreation是该type下的最大值:
SELECT u.id, u.dtCreation, u.type FROM users u WHERE u.type IN ('aaa','bbb','ccc') AND NOT EXISTS ( SELECT 1 FROM users u2 WHERE u2.type = u.type AND u2.dtCreation > u.dtCreation );
内容的提问来源于stack exchange,提问作者Xiidref
相关产品推荐
相关产品推荐

