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

Posted

技术标签:

【中文标题】如何忽略 PostgreSQL 窗口函数中的空值?或返回列中的下一个非空值【英文标题】:How to ignore nulls in PostgreSQL window functions? or return the next non-null value in a column 【发布时间】:2016-05-26 21:01:35 【问题描述】:

假设我有下表:

 | User_id |   COL1   | COL2 |
 +---------+----------+------+
 | 1       |          | 1    |
 | 1       |          | 2    | 
 | 1       |   2421   |      | 
 | 1       |          | 1    | 
 | 1       |   3542   |      | 
 | 2       |          | 1    |

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

 | User_id |   COL1   | COL2 | COL3 |
 +---------+----------+------+------
 | 1       |          | 1    | 2421 |
 | 1       |          | 2    | 2421 |
 | 1       |   2421   |      |      |
 | 1       |          | 1    | 3542 |
 | 1       |   3542   |      |      |
 | 2       |          | 1    |      |

SELECT 
first_value(COL1 ignore nulls) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;

可以,但我使用的是不支持忽略 null 子句的 PostgreSQL。

有什么建议的解决方法吗?

【问题讨论】:

您需要一列来指定排序。 SQL 表本质上是无序的。 【参考方案1】:

如果您在订单中添加条件时,您仍然可以使用窗口功能执行此操作,如下所示:

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

这将首先使用非空值。

但是,与跳过空值相比,性能可能不会很好,因为数据库必须根据其他条件进行排序。

【讨论】:

但这与IGNORE NULLS 子句并不完全一样。 一个postgresql不支持atm的子句【参考方案2】:

我也遇到了同样的问题。其他解决方案可能有效,但我必须为我需要的每一行构建多个窗口。

你可以试试这个 sn-ps:https://wiki.postgresql.org/wiki/First/last_(aggregate)

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

SELECT 
first(COL1) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;

【讨论】:

【参考方案3】:

总是有使用相关子查询的行之有效的方法:

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;

【讨论】:

运行此程序时未找到 t2.id >= t.id 过滤器中的 t.id @user3558238 。 . .找不到是什么意思? t 是外查询中表的别名; t2 是内部查询中的别名。 是说t.user_id不存在,可能是PostgreSQL中子查询不能引用外部查询参数? @user3558238 。 . . Postgres 绝对支持相关子查询。您应该编辑您的问题并包括您的尝试。【参考方案4】:

希望这会有所帮助,

SELECT * FROM TABLE ORDER BY COALESCE(colA, colB);

按 colA 排序,如果 colA 的值为 NULL,则按 colB 排序。

【讨论】:

【参考方案5】:

您可以使用COALESCE() 函数。对于您的查询:

SELECT 
first_value(COALESCE(COL1)) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;

但我不明白使用 COL2 排序的原因是什么,因为此行对 COL2 具有空值:

 | User_id |   COL1   | COL2 |
 +---------+----------+------+
 | 1       |          | 1    |
 | 1       |          | 2    | 
 | 1       |   2421   |      | <<--- null?
 | 1       |          | 1    | 
 | 1       |   3542   |      | <<--- null?
 | 2       |          | 1    |

【讨论】:

以上是关于如何忽略 PostgreSQL 窗口函数中的空值?或返回列中的下一个非空值的主要内容,如果未能解决你的问题,请参考以下文章

将列分组为一行,忽略 postgreSQL 中的空值

如何定义一个维度,以便在显示所有值时不忽略 FK 中的空值?

“‘密码’的空值”——DataGrip 中的 PostgreSQL

sqlite - 忽略 lag/lad 中的空值

Linux/bash 解析文本输出,选择字段,仅忽略一个字段中的空值

Hive 忽略空值