SQL如何按id分组选取b不为null的最后一个对应a值?
按id分组取b非null记录最大a对应行的SQL解决方案
原始数据结构
| id | a | b |
|---|---|---|
| 1 | 1 | kate |
| 1 | 4 | null |
| 1 | 3 | paul |
| 1 | 3 | paul |
| 1 | 2 | lola |
| 2 | 1 | kim |
| 2 | 9 | null |
| 2 | 2 | null |
预期结果
| id | a | b |
|---|---|---|
| 1 | 3 | paul |
| 2 | 1 | kim |
原SQL问题分析
你的原SQL存在两个问题:
- 语法错误:子查询
select后多了冗余逗号,也未声明要查询的id、a字段 - 逻辑错误:排序前未过滤
b为null的记录,导致分组内a最大但b为null的行被排在首位,最终返回null
解决方案
方案1:先过滤非null记录再取分组Top1(通用兼容方案)
该方案直接匹配你的需求,兼容所有支持窗口函数的数据库版本:
SELECT id, a, b FROM ( SELECT id, a, b, ROW_NUMBER() OVER (PARTITION BY id ORDER BY a DESC) AS rn FROM your_table_name WHERE b IS NOT NULL -- 提前过滤b为null的无效记录 ) t WHERE rn = 1;
方案2:实现类似pandas ffill的空值填充效果
如果你需要保留所有原始行、对b字段按a降序排序后向前填充非null值,可使用支持IGNORE NULLS参数的窗口函数实现(支持MySQL 8.0.22+、PostgreSQL、Oracle等数据库):
SELECT id, a, LAST_VALUE(b) OVER ( PARTITION BY id ORDER BY a DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW IGNORE NULLS ) AS filled_b FROM your_table_name;
执行后如果仅需要每个id的最终填充结果,加一层去重取每个id的第一条即可。
内容的提问来源于stack exchange,提问作者user458
相关产品推荐
相关产品推荐

