有没有一种方法可以计算一列中NULL之间的非null数量?

时间:2019-08-22 12:14:57

标签: sql sql-server

我有一个查询在查询财务数字和标志是否达到目标。我有一个列,如果命中目标,则填充1,如果未命中目标,则为NULL。这是一个简单的CASE语句。

我需要能够计算该列中有多少连续的行填充有1,然后在击中NULL时停止计数,然后从下一个非null开始重新计数。

我尝试了所有可能想到的“ COUNT(*)OVER”组合,但都没有给我所需的结果。

我会发布整个查询,因为它不会太长-

SELECT
    *,
    CASE
        WHEN zzz.Flag_hit_Target IS NOT NULL THEN COUNT(*) OVER (PARTITION BY zzz.Flag_hit_Target ORDER BY CAST(zzz.Close_month as DATE) DESC)  
        ELSE NULL
    END AS Counter
FROM
(   
    SELECT
        zz.Close_month,
        SUM(MRP) as Total_MRP,
        zz.Target,
        CASE
            WHEN SUM(MRP) >= zz.Target THEN 1
            ELSE NULL
        END AS Flag_hit_target
    FROM
    (
        SELECT
            Opp.id,
            opp.MRP__c as MRP,
            1500 as Target,
            CONCAT(DATENAME(month, Closedate), ' ', DATEPART(year, Closedate)) as Close_month
        FROM Table1 as Opp WITH (NOLOCK)    
        WHERE OPP_type__c = 'Opp Type 1'
        AND Appointment_setter1__c = 'Person 1'
        AND Stagename = 'Closed (Won)'
    ) as zz
    GROUP BY zz.Close_month, zz.Target
) as zzz
ORDER by CAST(zzz.Close_month as DATE) desc

通过此操作,我得到以下结果-

+----------------+-----------------+---------+
|  Close_month   | Flag_hit_target | Counter |
+----------------+-----------------+---------+
| June 2019      | NULL            | NULL    |
| April 2019     | NULL            | NULL    |
| March 2019     | 1               | 1       |
| February 2019  | NULL            | NULL    |
| January 2019   | 1               | 2       |
| November 2018  | NULL            | NULL    |
| October 2018   | NULL            | NULL    |
| September 2018 | NULL            | NULL    |
| July 2018      | NULL            | NULL    |
| June 2018      | 1               | 3       |
| May 2018       | NULL            | NULL    |
| April 2018     | 1               | 4       |
| March 2018     | NULL            | NULL    |
| February 2018  | 1               | 5       |
| January 2018   | 1               | 6       |
| December 2017  | 1               | 7       |
| October 2017   | NULL            | NULL    |
| September 2017 | 1               | 8       |
| August 2017    | 1               | 9       |
| July 2017      | 1               | 10      |
| June 2017      | 1               | 11      |
| May 2017       | NULL            | NULL    |
| April 2017     | 1               | 12      |
| March 2017     | NULL            | NULL    |
| February 2017  | 1               | 13      |
| January 2017   | 1               | 14      |
+----------------+-----------------+---------+

我追求的结果如下(注意最后一栏)-

+----------------+-----------------+---------+
|  Close_month   | Flag_hit_target | Counter |
+----------------+-----------------+---------+
| June 2019      | NULL            | NULL    |
| April 2019     | NULL            | NULL    |
| March 2019     | 1               | 1       |
| February 2019  | NULL            | NULL    |
| January 2019   | 1               | 1       |
| November 2018  | NULL            | NULL    |
| October 2018   | NULL            | NULL    |
| September 2018 | NULL            | NULL    |
| July 2018      | NULL            | NULL    |
| June 2018      | 1               | 1       |
| May 2018       | NULL            | NULL    |
| April 2018     | 1               | 1       |
| March 2018     | NULL            | NULL    |
| February 2018  | 1               | 3       |
| January 2018   | 1               | 2       |
| December 2017  | 1               | 1       |
| October 2017   | NULL            | NULL    |
| September 2017 | 1               | 4       |
| August 2017    | 1               | 3       |
| July 2017      | 1               | 2       |
| June 2017      | 1               | 1       |
| May 2017       | NULL            | NULL    |
| April 2017     | 1               | 1       |
| March 2017     | NULL            | NULL    |
| February 2017  | 1               | 2       |
| January 2017   | 1               | 1       |
+----------------+-----------------+---------+

谢谢!

2 个答案:

答案 0 :(得分:2)

一种解决方案是对所有记录使用ROW_NUMBER,然后对每个日期减去最后ROW_NUMBER条记录的NULL值。

设置

IF OBJECT_ID('tempdb..#Test') IS NOT NULL
    DROP TABLE #Test

CREATE TABLE #Test (
    Date DATE,
    Flag BIT)

INSERT INTO #Test (
    Date,
    Flag)
VALUES
    ('2019-09-01', NULL),
    ('2019-08-01', NULL),
    ('2019-07-01', 1),
    ('2019-06-01', NULL),
    ('2019-05-01', 1),
    ('2019-04-01', NULL),
    ('2019-03-01', NULL),
    ('2019-02-01', NULL),
    ('2019-01-01', 1),
    ('2018-12-01', NULL),
    ('2018-11-01', 1),
    ('2018-10-01', NULL),
    ('2018-09-01', 1),
    ('2018-08-01', 1),
    ('2018-07-01', 1),
    ('2018-06-01', NULL),
    ('2018-05-01', 1),
    ('2018-04-01', 1),
    ('2018-03-01', 1),
    ('2018-02-01', 1),
    ('2018-01-01', NULL)

解决方案

;WITH DataWithRowNumber AS
(
    SELECT
        T.*,
        RowNumber = -1 + ROW_NUMBER() OVER (ORDER BY T.Date)
    FROM
        #Test AS T
)
SELECT
    D.Date,
    D.Flag,
    D.RowNumber,
    M.MaxPreviousNullRowNumber,
    RowNumberRest = D.RowNumber - M.MaxPreviousNullRowNumber,
    Counter = CASE WHEN D.Flag IS NOT NULL THEN D.RowNumber - M.MaxPreviousNullRowNumber END
FROM
    DataWithRowNumber AS D
    OUTER APPLY (
        SELECT
            MaxPreviousNullRowNumber = MAX(R.RowNumber)
        FROM
            DataWithRowNumber AS R
        WHERE
            R.Date < D.Date AND
            R.Flag IS NULL) AS M
ORDER By
    D.RowNumber DESC

结果

+------------+------+-----------+--------------------------+---------------+---------+
|    Date    | Flag | RowNumber | MaxPreviousNullRowNumber | RowNumberRest | Counter |
+------------+------+-----------+--------------------------+---------------+---------+
| 2019-09-01 | NULL |        20 | 19                       | 1             | NULL    |
| 2019-08-01 | NULL |        19 | 17                       | 2             | NULL    |
| 2019-07-01 | 1    |        18 | 17                       | 1             | 1       |
| 2019-06-01 | NULL |        17 | 15                       | 2             | NULL    |
| 2019-05-01 | 1    |        16 | 15                       | 1             | 1       |
| 2019-04-01 | NULL |        15 | 14                       | 1             | NULL    |
| 2019-03-01 | NULL |        14 | 13                       | 1             | NULL    |
| 2019-02-01 | NULL |        13 | 11                       | 2             | NULL    |
| 2019-01-01 | 1    |        12 | 11                       | 1             | 1       |
| 2018-12-01 | NULL |        11 | 9                        | 2             | NULL    |
| 2018-11-01 | 1    |        10 | 9                        | 1             | 1       |
| 2018-10-01 | NULL |         9 | 5                        | 4             | NULL    |
| 2018-09-01 | 1    |         8 | 5                        | 3             | 3       |
| 2018-08-01 | 1    |         7 | 5                        | 2             | 2       |
| 2018-07-01 | 1    |         6 | 5                        | 1             | 1       |
| 2018-06-01 | NULL |         5 | 0                        | 5             | NULL    |
| 2018-05-01 | 1    |         4 | 0                        | 4             | 4       |
| 2018-04-01 | 1    |         3 | 0                        | 3             | 3       |
| 2018-03-01 | 1    |         2 | 0                        | 2             | 2       |
| 2018-02-01 | 1    |         1 | 0                        | 1             | 1       |
| 2018-01-01 | NULL |         0 | NULL                     | NULL          | NULL    |
+------------+------+-----------+--------------------------+---------------+---------+

答案 1 :(得分:0)