【问题标题】:How to ignore nulls in PostgreSQL window functions? or return the next non-null value in a column如何忽略 PostgreSQL 窗口函数中的空值?或返回列中的下一个非空值
【发布时间】: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 表本质上是无序的。

标签: sql postgresql


【解决方案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    |
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-23
        • 2019-11-05
        • 1970-01-01
        • 2019-12-07
        • 2012-01-09
        • 1970-01-01
        相关资源
        最近更新 更多