You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PostgreSQL中最后一个非NULL值填充列中的NULL值

问题描述

我有一个PostgreSQL表,结构及数据如下:

CREATE TABLE cte1 (
    entity_id INT,
    assignedtogroup INT,
    time BIGINT
);

INSERT INTO cte1 (entity_id, assignedtogroup, time)
VALUES
    (1, 435198, 1687863949740),
    (1, 435198, 1687863949741),
    (1, NULL, 1687863949742),
    (1, NULL, 1687863949743),
    (1, 435224, 1687863949744),
    (1, 435224, 1687863949745),
    (1, 435143, 1687863949746),
    (1, 435143, 1687863949747),
    (1, 435191, 1687863949748),
    (1, NULL, 1687863949749),
    (2, 435143, 1690452125291),
    (2, 435143, 1690452125292),
    (2, 435191, 1690452125293),
    (2, NULL, 1690452125294);

我需要用同一entity_id下时间上紧邻当前行的前一行非NULL值,填充assignedtogroup列中的空值,预期结果如下:

entity_idassignedtogrouptime
14351981687863949740
14351981687863949741
14351981687863949742
14351981687863949743
14352241687863949744
14352241687863949745
14351431687863949746
14351431687863949747
14351911687863949748
14351911687863949749
24351431690452125291
24351431690452125292
24351911690452125293
24351911690452125294

请问仅通过SELECT语句能否实现该需求?

我尝试了用LAG函数,但结果仍存在NULL值,且entity_id为2的数据出现混乱:

SELECT
    entity_id,
    COALESCE(
        assignedtogroup,
        LAG(assignedtogroup) OVER (PARTITION BY entity_id ORDER BY time)
    ) AS filled_assignedtogroup
FROM cte1;

解决方案

可以仅通过SELECT语句实现,以下是两种可行方案:

方法1:使用LAST_VALUE + IGNORE NULLS(PostgreSQL 11+支持)

SELECT
    entity_id,
    LAST_VALUE(assignedtogroup) OVER (
        PARTITION BY entity_id 
        ORDER BY time 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        IGNORE NULLS
    ) AS assignedtogroup,
    time
FROM cte1
ORDER BY entity_id, time;

方法2:使用MAX()窗口函数(兼容旧版本PostgreSQL)

SELECT
    entity_id,
    MAX(assignedtogroup) OVER (
        PARTITION BY entity_id, grp
    ) AS assignedtogroup,
    time
FROM (
    SELECT
        *,
        COUNT(assignedtogroup) OVER (
            PARTITION BY entity_id 
            ORDER BY time
        ) AS grp
    FROM cte1
) t
ORDER BY entity_id, time;

方案说明

  • 方法1:LAST_VALUE(assignedtogroup) ... IGNORE NULLS会在窗口范围内(从当前分组开头到当前行)忽略NULL值,自动取最后一个非NULL值,完美匹配用最近前序非NULL值填充的需求。
  • 方法2:先通过COUNT(assignedtogroup)生成分组标识grp,每遇到一个非NULL值,grp就递增,连续的NULL值会和前面的非NULL值归为同一分组,再用MAX()提取分组内的非NULL值完成填充。

内容的提问来源于stack exchange,提问作者executable

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:55:25