如何忽略PostgreSQL窗口函数中的空值?或返回列中的下一个非空值

use*_*238 8 sql postgresql

可以说我有下表:

 | User_id |   COL1   | COL2 |
 +---------+----------+------+
 | 1       |          | 1    |
 | 1       |          | 2    | 
 | 1       |   2421   |      | 
 | 1       |          | 1    | 
 | 1       |   3542   |      | 
 | 2       |          | 1    |
Run Code Online (Sandbox Code Playgroud)

我需要另一列指示每一行的下一个非空COL1值,因此结果将如下所示:

 | User_id |   COL1   | COL2 | COL3 |
 +---------+----------+------+------
 | 1       |          | 1    | 2421 |
 | 1       |          | 2    | 2421 |
 | 1       |   2421   |      |      |
 | 1       |          | 1    | 3542 |
 | 1       |   3542   |      |      |
 | 2       |          | 1    |      |
Run Code Online (Sandbox Code Playgroud)
SELECT 
first_value(COL1 ignore nulls) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;
Run Code Online (Sandbox Code Playgroud)

可以工作,但是我正在使用不支持ignore nulls子句的PostgreSQL。

有建议的解决方法吗?

Seb*_*ien 8

如果您按以下方式添加条件(按顺序)时,仍然可以使用开窗功能来执行此操作:

select
   first_value(COL1) 
   over (
     partition by user_id 
     order by case when COL1 is not null then 0 else 1 end ASC, COL2 
     rows unbounded following
   ) 
from table
Run Code Online (Sandbox Code Playgroud)

这将首先使用非null值。

但是,跳过空值的性能可能不会很好,因为数据库将不得不根据其他条件进行排序。


小智 7

我也有同样的问题。其他解决方案可能会起作用,但是我必须为我需要的每一行构建多个窗口。

您可以尝试以下代码段:https ://wiki.postgresql.org/wiki/First/last_( aggregate)

如果创建聚合,则可以使用它们:

SELECT 
first(COL1) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 2

使用相关子查询总是有经过验证的正确方法:

select t.*,
       (select t2.col1
        from t t2
        where t2.id >= t.id and t2.col1 is not null
        order by t2.id desc
        fetch first 1 row only
       ) as nextcol1
from t;
Run Code Online (Sandbox Code Playgroud)