首页 > 解决方案 > 计算日期之间的空值

问题描述

我正在尝试计算日期之间的空值数量。

我的表如下所示:

transaction_date    transaction_sale
10/1/2018           NULL
11/1/2018           33
12/1/2018           NULL
1/1/2019            NULL
2/1/2019            NULL
3/1/2019            2
4/1/2019            NULL
5/1/2019            NULL
6/1/2019            10

我正在寻找以下输出:

transaction_date    transaction_sale   count
10/1/2018           NULL               NULL
11/1/2018           33                 1
12/1/2018           NULL               NULL
1/1/2019            NULL               NULL
2/1/2019            NULL               NULL
3/1/2019            2                  3
4/1/2019            NULL               NULL
5/1/2019            NULL               NULL
6/1/2019            10                 2

标签: sqlpostgresqlwindow-functionsgaps-and-islands

解决方案


count(expression)不计算 NULL 值,无论是作为聚合函数还是作为窗口函数。手册:

表达式的值不为空的输入行数

这是简单快速查询的关键要素。

假设transaction_date就像UNIQUE您的示例所暗示的那样,或者您必须定义如何打破重复值之间的联系。(实际的表定义会澄清。)

SELECT transaction_date, transaction_sale
     , CASE WHEN transaction_sale IS NOT NULL
            THEN count(*) OVER (PARTITION BY grp) - 1
       END AS count 
FROM  (
   SELECT *
        , count(transaction_sale) OVER (ORDER BY transaction_date DESC) AS grp
   FROM   tbl
   ) sub
ORDER  BY transaction_date;

在子查询中形成组。由于每个非空值都会根据您的定义启动一个新组,因此只需在窗口函数中按降序计算实际值,即可有效地为每一行分配一个组号。其余的都是微不足道的。

在外部SELECT,计算每组的行数并显示位置transaction_sale IS NOT NULL。按 1 修正。瞧。

有关的:

或者,用 - 计数FILTER (WHERE transaction_sale IS NULL)对于我们不能简单地减去1的相关情况很有用:

SELECT transaction_date, transaction_sale
     , CASE WHEN transaction_sale IS NOT NULL
            THEN count(*) FILTER (WHERE transaction_sale IS NULL)
                          OVER (PARTITION BY grp)
       END AS count 
FROM  (
   SELECT *
        , count(transaction_sale) OVER (ORDER BY transaction_date DESC) AS grp
   FROM   tbl
   ) sub
ORDER  BY transaction_date;

关于FILTER条款:

db<>在这里摆弄


推荐阅读