如何用SQL按A→B→C优先级获取每个Key的最大行?
按多列优先级分组获取最大行的SQL实现
问题描述
我有一张表,需要为每个Key获取符合优先级规则的最大行,判定规则如下:
- 优先选取A列值最大的行;
- 若A列值相同,选取其中B列值最大的行;
- 若B列值仍相同,选取其中C列值最大的行。
示例表数据:
Key, A, B, C 1, 1, 2, 1 1, 2, 1, 3 1, 1, 1, 1 1, 2, 1, 2 2, 2, 1, 2 2, 2, 2, 3 2, 1, 2, 2 2, 1, 2, 1
期望结果:
Key, A, B, C 1, 2, 1, 3 2, 2, 2, 3
解决方案
方法一:窗口函数实现(推荐,通用)
这是现代SQL数据库(MySQL 8.0+、PostgreSQL、SQL Server、Oracle等)最简洁高效的实现方式,利用ROW_NUMBER()窗口函数按规则排序并筛选每组的首行:
SELECT Key, A, B, C FROM ( SELECT Key, A, B, C, ROW_NUMBER() OVER ( PARTITION BY Key ORDER BY A DESC, B DESC, C DESC ) AS row_rank FROM your_table_name ) ranked_data WHERE row_rank = 1;
逻辑说明:
PARTITION BY Key:将数据按Key分组,确保每个Key单独处理;ORDER BY A DESC, B DESC, C DESC:在每组内按照优先级从高到低排序(A优先,其次B,最后C);ROW_NUMBER()为每组内的行分配唯一序号,序号为1的行就是该Key下符合规则的最大行。
方法二:关联子查询实现(兼容旧版数据库)
如果你的数据库不支持窗口函数(如MySQL 5.x),可以用关联子查询筛选出不存在更高优先级的行:
SELECT t1.Key, t1.A, t1.B, t1.C FROM your_table_name t1 WHERE NOT EXISTS ( SELECT 1 FROM your_table_name t2 WHERE t2.Key = t1.Key AND ( t2.A > t1.A OR (t2.A = t1.A AND t2.B > t1.B) OR (t2.A = t1.A AND t2.B = t1.B AND t2.C > t1.C) ) );
逻辑说明:
- 子查询会检查同
Key下是否存在比当前行t1优先级更高的行t2; - 如果不存在这样的
t2行,说明t1就是该Key下符合规则的最大行。
内容的提问来源于stack exchange,提问作者user3879322
相关产品推荐
相关产品推荐

