从NOT NULL重新开始的NULL累积计数

时间:2018-12-27 19:34:11

标签: sql-server tsql

我想添加一列,该数字表示通过在PERSON_ID上划分分区并按INVITED_DATE排序时递增地计算非null之前的null列的数量,从而在接受之前邀请一个人。

我的表格具有以下格式:

| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE |
| 12345     | 567       | 12-01-18     | NULL          |
| 12346     | 567       | 12-02-18     | NULL          |
| 12347     | 567       | 12-03-18     | NULL          |
| 12348     | 567       | 12-04-18     | 12-04-18      |
| 12349     | 567       | 12-05-18     | NULL          |
| 12350     | 568       | 12-01-18     | NULL          |
| 12351     | 568       | 12-02-18     | 12-02-18      |

理想情况下,输出应如下所示:

| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE | INVITES_BEFORE_ACCEPT |
| 12345     | 567       | 12-01-18     | NULL          |  1                    |
| 12346     | 567       | 12-02-18     | NULL          |  2                    |
| 12347     | 567       | 12-03-18     | NULL          |  3                    |
| 12348     | 567       | 12-04-18     | 12-04-18      |  0                    |
| 12349     | 567       | 12-05-18     | NULL          |  1                    |
| 12350     | 568       | 12-01-18     | NULL          |  1                    |
| 12351     | 568       | 12-02-18     | 12-02-18      |  0                    |

到目前为止,我已经尝试了使用OVER和PARTITION对ROW NUMBER进行多次迭代,但是我发现它必须是外部应用。以下OUTER APPLY会计算数据,但不会成功接受就重新开始计数。

SELECT t.* , invites.INVITES_BEFORE_ACCEPT
FROM table t
OUTER APPLY (
    SELECT COUNT(*) INVITES_BEFORE_ACCEPT
    FROM table t2
    WHERE t.PERSON_ID = t2.PERSON_ID and t.INVITED_DATE < t2.ACCEPTED_DATE
            ) invites

1 个答案:

答案 0 :(得分:2)

一种方法是

WITH t
     AS (SELECT *,
                COUNT(ACCEPTED_DATE)
                  OVER (
                    PARTITION BY PERSON_ID
                    ORDER BY INVITED_DATE) AS Grp
         FROM   [table])
SELECT *,
       SUM(CASE
             WHEN ACCEPTED_DATE IS NULL
               THEN 1
             ELSE 0
           END)
         OVER (
           PARTITION BY PERSON_ID, Grp
           ORDER BY INVITED_DATE) AS INVITES_BEFORE_ACCEPT
FROM   t 

Demo