PostgreSQL按行分组:填充null值的group_line_num字段
PostgreSQL 填充分组内Null值为前序非Null值
针对你需要将后续Null的group_line_num替换为前一个非Null值(或按unit='PST^'分组)的需求,可以通过窗口函数结合分组标识实现,具体方案如下:
解决方案SQL
SELECT item_id, ordered_qty, unit, line_num, -- 取分组内第一个非Null的group_line_num作为填充值 FIRST_VALUE(group_line_num) OVER (PARTITION BY group_id ORDER BY line_num) AS filled_group_line_num, code FROM ( SELECT *, -- 生成分组ID:遇到unit为PST^或group_line_num非Null时,分组计数+1 SUM(CASE WHEN unit = 'PST^' OR group_line_num IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY line_num ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS group_id FROM your_table_name ORDER BY line_num ) AS grouped_data;
代码解释
- 内层子查询生成分组ID:
- 利用
SUM() OVER()窗口函数,按line_num排序,每遇到unit='PST^'或group_line_num非Null的行就累加1,让同一组(从标识行到下一个标识行前)的行拥有相同group_id。
- 利用
- 外层查询填充Null值:
- 通过
FIRST_VALUE(group_line_num) OVER(PARTITION BY group_id ORDER BY line_num),在每个分组内取第一个非Null的group_line_num,自动填充该组内所有Null行。
- 通过
样本数据执行结果
按你的样本数据执行后,filled_group_line_num列会得到如下结果:
| item_id | ordered_qty | unit | line_num | filled_group_line_num | code |
|---|---|---|---|---|---|
| NP4484140T | 11 | PST^ | 7 | 7 | |
| COL48LPT | 6 | PST | 8 | 7 | NP4484140T |
| COL48EPT | 4 | PST | 9 | 7 | NP4484140T |
| COL48BPT | 1 | PST | 10 | 7 | NP4484140T |
| VP5578135T | 1 | PST^ | 52 | 52 | |
| ONTP48CPT | 1 | PST | 53 | 52 | VP5578135T |
替代方案(MAX函数)
如果分组内仅首行有group_line_num值,也可以用MAX()函数替代,效果一致:
SELECT item_id, ordered_qty, unit, line_num, MAX(group_line_num) OVER (PARTITION BY group_id) AS filled_group_line_num, code FROM ( SELECT *, SUM(CASE WHEN unit = 'PST^' OR group_line_num IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY line_num ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS group_id FROM your_table_name ORDER BY line_num ) AS grouped_data;
内容的提问来源于stack exchange,提问作者anthonyabc
相关产品推荐
相关产品推荐

