如何在MySQL中筛选每组严格唯一最大值所在行
解决方案
原表 tab1 结构与数据
| id | obj | col2 | val |
|---|---|---|---|
| 1 | obj1 | item1 | 2 |
| 2 | obj2 | item2 | 5 |
| 3 | obj1 | item3 | 4 |
| 4 | obj2 | item1 | 5 |
| 5 | obj3 | item4 | 2 |
| 6 | obj3 | item2 | 1 |
期望输出
| id | obj | col2 | val |
|---|---|---|---|
| 3 | obj1 | item3 | 4 |
| 5 | obj3 | item4 | 2 |
你之前写的SQL有两个问题:一是不符合SQL标准(非聚合字段id、col2未包含在GROUP BY中,不同数据库执行结果可能混乱);二是没过滤掉最大值重复的分组(比如obj2里val=5出现两次,不满足“严格大于同组其他所有值”的要求)。
下面给两种可行的正确写法:
方法一:用窗口函数(推荐,支持MySQL8+、PostgreSQL、SQL Server等)
SELECT id, obj, col2, val FROM ( SELECT *, -- 给每个obj分组按val降序排名,最大值行排第1 RANK() OVER (PARTITION BY obj ORDER BY val DESC) AS rnk, -- 统计每个obj分组内相同val的行数 COUNT(*) OVER (PARTITION BY obj, val) AS val_count FROM tab1 ) t -- 只取排名第1且该val在组内仅出现一次的行 WHERE rnk = 1 AND val_count = 1;
方法二:用分组子查询(兼容低版本数据库)
SELECT t1.* FROM tab1 t1 JOIN ( SELECT obj, MAX(val) AS max_val FROM tab1 GROUP BY obj -- 确保组内只有一行等于最大值(即最大值唯一) HAVING COUNT(*) = COUNT(CASE WHEN val = MAX(val) THEN 1 END) ) t2 ON t1.obj = t2.obj AND t1.val = t2.max_val;
内容的提问来源于stack exchange,提问作者Harikesh Pratap Singh
相关产品推荐
相关产品推荐

