Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 计数给定ID的连续空值_Sql_Sql Server_Common Table Expression_Cumulative Sum - Fatal编程技术网

Sql 计数给定ID的连续空值

Sql 计数给定ID的连续空值,sql,sql-server,common-table-expression,cumulative-sum,Sql,Sql Server,Common Table Expression,Cumulative Sum,我试图创建一个查询,当帐户在[Volume]表中没有条目时,该查询包含ISO周的运行计数。查询只返回帐户的一个样本,因此我创建了几个CTE来限制记录的数量,并加入volume表,以便在结果中显示没有卷的周数 为了说明我想要的结果: ISOWk | SurrID | Weekly Volume | No vol Count 201601 | 001 | 0 | 1 201601 | 002 | 5 | 0 201602 | 001 |

我试图创建一个查询,当帐户在[Volume]表中没有条目时,该查询包含ISO周的运行计数。查询只返回帐户的一个样本,因此我创建了几个CTE来限制记录的数量,并加入volume表,以便在结果中显示没有卷的周数

为了说明我想要的结果:

ISOWk | SurrID | Weekly Volume | No vol Count

201601 |    001 |      0 |       1
201601 |    002 |      5 |       0
201602 |    001 |      0 |       2
201602 |    002 |      0 |       1
201603 |    001 |     125|       0
201603 |    002 |     75 |       0
201604 |    001 |      0 |       1
201604 |    002 |     75 |       0
如您所见,SurrID 001的账户在201601周和201602周没有交易量,因此在201602周[no vol Count]为2。在第201603周中,存在音量,因此计数器重置为0,并在第201604周增加到1

根据我所做的研究,我已经成功地使用带有窗口功能的行数运行了一个连续的计数,但如果有音量,它不会重置(如我的示例中的201603周)。我搞不懂的是如何计算连续的零值,并在需要时重置

我在下面列出了我的完整查询,以便您了解完整情况(请在这里指出任何特别糟糕的做法-我仍在寻找我的方法!)。在我加入第三个CTE“NDs”之前,一切都按预期进行。然后需要45分钟才能返回刚刚超过2000行的数据,并返回未显示每周卷的数据行的非重置计数

WITH Surrs AS
    (
        SELECT SurrID, OracleStartDate AS OSD
        FROM (
                SELECT ca.SurrID, OracleStartDate, ROW_NUMBER() OVER(ORDER BY OracleStartDate) as rn
                FROM tblCustomerAccounts ca
                JOIN tblAccountUpdates au
                    ON ca.SurrID = au.SurrID
                WHERE CustomerType_ID IN (1,2,3,4,5,6,7,12)
                    AND au.ISOWk = 201641
            ) a
        WHERE rn % 1000 = 0
    ),
    Updates AS
    (
        SELECT au.ISOWk, s.SurrID, (CASE WHEN AccStatus_ID = 1 THEN 'A' ELSE 'I' END) AS AccStatus, (CASE WHEN dbo.udf_ConvertDateToISOWeek(OSD) <= BBC THEN 'B' ELSE 'F' END) AS Book
        FROM Surrs s            
        JOIN (
                SELECT  ISOWk,
                        (SELECT BBCutOff FROM dbo.udf_CutOffWeeks(ISOWk)) AS BBC,
                        (SELECT FYStart FROM dbo.udf_CutOffWeeks(ISOWk)) AS FYS,
                        (SELECT FYEnd FROM dbo.udf_CutOffWeeks(ISOWk)) AS FYE,
                        (SELECT BYStart FROM dbo.udf_CutOffWeeks(ISOWk)) AS BYS,
                        (SELECT BYEnd FROM dbo.udf_CutOffWeeks(ISOWk)) AS BYE,
                        SurrID,
                        AccStatus_ID
                FROM tblAccountUpdates
            ) au
            ON au.SurrID = s.SurrID
    ), 
    NDs AS 
    (
        SELECT u.ISOWk, u.SurrID, ROW_NUMBER() OVER (PARTITION BY u.SurrID ORDER BY u.ISOWk) AS NDCount
        FROM Updates u
        LEFT JOIN tblTotalVolumes tv
            ON u.SurrID = tv.SurrID
            AND u.ISOWk = tv.ISOWk
        WHERE tv.Volume IS NULL
            AND u.ISOWk >= 201601

    )
SELECT  tw.ISOWk, 
        tw.SurrID, 
        (CASE WHEN Volume IS NULL THEN 0 ELSE Volume END) AS [Weekly Volume], 
        tw.Book, 
        tw.AccStatus,
        (CASE WHEN tw.AccStatus = 'I' AND lw.AccStatus = 'A' THEN 'Y' ELSE '' END) AS [Stopped this week],
        (CASE WHEN tw.AccStatus = 'A' AND lw.AccStatus = 'I' THEN 'Y' ELSE '' END) AS [Restarted this week],
        (CASE WHEN NDCount IS NULL THEN 0 ELSE NDCount END) AS [Consecutive ND Weeks]

FROM Updates tw
JOIN Updates lw
    ON lw.ISOWk = dbo.udf_ConvertDateToISOWeek(DATEADD("ww",-1,dbo.udf_ConvertISOWkToDate(tw.ISOWk)))
    AND tw.SurrID = lw.SurrID
LEFT JOIN tblTotalVolumes tv
    ON tw.SurrID = tv.SurrID
    AND tw.ISOWk = tv.ISOWk
LEFT JOIN NDs
    ON tw.SurrID = nds.SurrID
    AND tw.ISOWk = nds.ISOWk

ORDER BY tw.ISOWk
在我的数据集中还有这个问题的其他实例。

以下是一种方法:

  • 计算
    SurrId
    前面非0值的数量。此编号标识组
  • 在每组中执行一个
    行编号()
  • 仅考虑<代码> RooNoMulk()/<代码>值为< > 0 < /C> > 这导致:

    select t.*,
           (case when weeklyvolume = 0
                 then row_number() over (partition by SurrId, grp order by ISOwk)
                 else 0
            end) as NoVolCount
    from (select t.*,
                 sum(case when weeklyvolume > 0 then 1 else 0 end) over (partition by SurrId order by ISOwk) as grp
          from t
         ) t;
    

    这看起来像是一个缺口和孤岛问题

    样本数据

    DECLARE @T TABLE(ISOWk int, SurrID char(3), WeeklyVolume int);
    INSERT INTO @T(ISOWk, SurrID, WeeklyVolume) VALUES
    (201601, '001',  0),
    (201601, '002',  5),
    (201602, '001',  0),
    (201602, '002',  0),
    (201603, '001',125),
    (201603, '002', 75),
    (201604, '001',  0),
    (201604, '002', 75),
    (201620, '003',  0),
    (201621, '003',  0),
    (201622, '003',  0),
    (201623, '003',  0),
    (201624, '003',  0),
    (201625, '003', 53),
    (201626, '003', 49),
    (201627, '003', 98),
    (201628, '003', 54),
    (201629, '003', 53),
    (201630, '003',103),
    (201631, '003', 59),
    (201632, '003', 35),
    (201633, '003',  0),
    (201634, '003',  0),
    (201635, '003',  0),
    (201636, '003',  0),
    (201637, '003', 87),
    (201638, '003',136),
    (201639, '003', 56),
    (201640, '003', 70),
    (201641, '003', 77),
    (201601, '004',  0),
    (201602, '004',  6),
    (201603, '004',  0),
    (201604, '004',  0);
    
    我用
    SurrID=003
    添加了你的扩展样本,用
    SurrID=004
    添加了我的样本

    查询

    WITH
    CTE
    AS
    (
        SELECT
            ISOWk
            ,SurrID
            ,WeeklyVolume
            ,ROW_NUMBER() OVER (PARTITION BY SurrID ORDER BY ISOWk) AS rn1
            ,ROW_NUMBER() OVER (PARTITION BY SurrID,WeeklyVolume ORDER BY ISOWk) AS rn2
        FROM @T
    )
    ,CTE2
    AS
    (
        SELECT
            ISOWk
            ,SurrID
            ,WeeklyVolume
            ,rn1
            ,rn2
            ,rn1-rn2 AS grp
            ,ROW_NUMBER() OVER (PARTITION BY SurrID,WeeklyVolume,rn1-rn2 ORDER BY ISOWk) AS rn3
        FROM CTE
    )
    SELECT
        ISOWk
        ,SurrID
        ,WeeklyVolume
        ,rn1
        ,rn2
        ,grp
        ,rn3
        ,CASE WHEN WeeklyVolume = 0 THEN rn3 ELSE 0 END AS NoVolumeCount
    FROM CTE2
    ORDER BY SurrID, ISOWk;
    
    结果

    +--------+--------+--------------+-----+-----+-----+-----+---------------+
    | ISOWk  | SurrID | WeeklyVolume | rn1 | rn2 | grp | rn3 | NoVolumeCount |
    +--------+--------+--------------+-----+-----+-----+-----+---------------+
    | 201601 |    001 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201602 |    001 |            0 |   2 |   2 |   0 |   2 |             2 |
    | 201603 |    001 |          125 |   3 |   1 |   2 |   1 |             0 |
    | 201604 |    001 |            0 |   4 |   3 |   1 |   1 |             1 |
    | 201601 |    002 |            5 |   1 |   1 |   0 |   1 |             0 |
    | 201602 |    002 |            0 |   2 |   1 |   1 |   1 |             1 |
    | 201603 |    002 |           75 |   3 |   1 |   2 |   1 |             0 |
    | 201604 |    002 |           75 |   4 |   2 |   2 |   2 |             0 |
    | 201620 |    003 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201621 |    003 |            0 |   2 |   2 |   0 |   2 |             2 |
    | 201622 |    003 |            0 |   3 |   3 |   0 |   3 |             3 |
    | 201623 |    003 |            0 |   4 |   4 |   0 |   4 |             4 |
    | 201624 |    003 |            0 |   5 |   5 |   0 |   5 |             5 |
    | 201625 |    003 |           53 |   6 |   1 |   5 |   1 |             0 |
    | 201626 |    003 |           49 |   7 |   1 |   6 |   1 |             0 |
    | 201627 |    003 |           98 |   8 |   1 |   7 |   1 |             0 |
    | 201628 |    003 |           54 |   9 |   1 |   8 |   1 |             0 |
    | 201629 |    003 |           53 |  10 |   2 |   8 |   1 |             0 |
    | 201630 |    003 |          103 |  11 |   1 |  10 |   1 |             0 |
    | 201631 |    003 |           59 |  12 |   1 |  11 |   1 |             0 |
    | 201632 |    003 |           35 |  13 |   1 |  12 |   1 |             0 |
    | 201633 |    003 |            0 |  14 |   6 |   8 |   1 |             1 |
    | 201634 |    003 |            0 |  15 |   7 |   8 |   2 |             2 |
    | 201635 |    003 |            0 |  16 |   8 |   8 |   3 |             3 |
    | 201636 |    003 |            0 |  17 |   9 |   8 |   4 |             4 |
    | 201637 |    003 |           87 |  18 |   1 |  17 |   1 |             0 |
    | 201638 |    003 |          136 |  19 |   1 |  18 |   1 |             0 |
    | 201639 |    003 |           56 |  20 |   1 |  19 |   1 |             0 |
    | 201640 |    003 |           70 |  21 |   1 |  20 |   1 |             0 |
    | 201641 |    003 |           77 |  22 |   1 |  21 |   1 |             0 |
    | 201601 |    004 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201602 |    004 |            6 |   2 |   1 |   1 |   1 |             0 |
    | 201603 |    004 |            0 |   3 |   2 |   1 |   1 |             1 |
    | 201604 |    004 |            0 |   4 |   3 |   1 |   2 |             2 |
    +--------+--------+--------------+-----+-----+-----+-----+---------------+
    
    我在结果中包含了中间列,因此您可以理解它是如何工作的

    间隙和孤岛的标准方法是两个
    行号序列
    ——一个是普通序列(
    rn1
    ),第二个是按
    周卷
    rn2
    )划分

    rn1
    rn2
    之间的差异给出了组(岛)的ID(
    grp
    )。计算由
    WeeklyVolume
    和该组(
    rn3
    )划分的另一个行号序列,并仅在
    WeeklyVolume
    为零时使用它

    显然,上面的所有内容首先是由
    SurrID
    划分的


    在答案的第一个变体中,我忘记了在
    rn3

    的最后一个分区中包含
    WeeklyVolume
    ,我已经修改了我的查询,以便可以使用您的格式,但是当一行有周卷时,
    [NoVolCount]
    不会重置,除非我错误地实现了您的解决方案。我已经编辑了我的帖子,如果你能看一看,我将不胜感激。这在很大程度上符合预期。然而,似乎存在一些值的组合,导致
    grp
    的值相同,尽管
    周量
    值不相同;从而导致错误的
    NoVolCount
    值。这是可能的,还是我的实现错了(在问题的上下文中)?@Andrewillams,请扩展示例数据,向我们展示这些特殊组合,并向我们展示您期望的结果。完美。这给了我预期的结果。您的建议非常有用,因为您提供了示例数据,我可以清楚地看到这是如何工作的。谢谢
    DECLARE @T TABLE(ISOWk int, SurrID char(3), WeeklyVolume int);
    INSERT INTO @T(ISOWk, SurrID, WeeklyVolume) VALUES
    (201601, '001',  0),
    (201601, '002',  5),
    (201602, '001',  0),
    (201602, '002',  0),
    (201603, '001',125),
    (201603, '002', 75),
    (201604, '001',  0),
    (201604, '002', 75),
    (201620, '003',  0),
    (201621, '003',  0),
    (201622, '003',  0),
    (201623, '003',  0),
    (201624, '003',  0),
    (201625, '003', 53),
    (201626, '003', 49),
    (201627, '003', 98),
    (201628, '003', 54),
    (201629, '003', 53),
    (201630, '003',103),
    (201631, '003', 59),
    (201632, '003', 35),
    (201633, '003',  0),
    (201634, '003',  0),
    (201635, '003',  0),
    (201636, '003',  0),
    (201637, '003', 87),
    (201638, '003',136),
    (201639, '003', 56),
    (201640, '003', 70),
    (201641, '003', 77),
    (201601, '004',  0),
    (201602, '004',  6),
    (201603, '004',  0),
    (201604, '004',  0);
    
    WITH
    CTE
    AS
    (
        SELECT
            ISOWk
            ,SurrID
            ,WeeklyVolume
            ,ROW_NUMBER() OVER (PARTITION BY SurrID ORDER BY ISOWk) AS rn1
            ,ROW_NUMBER() OVER (PARTITION BY SurrID,WeeklyVolume ORDER BY ISOWk) AS rn2
        FROM @T
    )
    ,CTE2
    AS
    (
        SELECT
            ISOWk
            ,SurrID
            ,WeeklyVolume
            ,rn1
            ,rn2
            ,rn1-rn2 AS grp
            ,ROW_NUMBER() OVER (PARTITION BY SurrID,WeeklyVolume,rn1-rn2 ORDER BY ISOWk) AS rn3
        FROM CTE
    )
    SELECT
        ISOWk
        ,SurrID
        ,WeeklyVolume
        ,rn1
        ,rn2
        ,grp
        ,rn3
        ,CASE WHEN WeeklyVolume = 0 THEN rn3 ELSE 0 END AS NoVolumeCount
    FROM CTE2
    ORDER BY SurrID, ISOWk;
    
    +--------+--------+--------------+-----+-----+-----+-----+---------------+
    | ISOWk  | SurrID | WeeklyVolume | rn1 | rn2 | grp | rn3 | NoVolumeCount |
    +--------+--------+--------------+-----+-----+-----+-----+---------------+
    | 201601 |    001 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201602 |    001 |            0 |   2 |   2 |   0 |   2 |             2 |
    | 201603 |    001 |          125 |   3 |   1 |   2 |   1 |             0 |
    | 201604 |    001 |            0 |   4 |   3 |   1 |   1 |             1 |
    | 201601 |    002 |            5 |   1 |   1 |   0 |   1 |             0 |
    | 201602 |    002 |            0 |   2 |   1 |   1 |   1 |             1 |
    | 201603 |    002 |           75 |   3 |   1 |   2 |   1 |             0 |
    | 201604 |    002 |           75 |   4 |   2 |   2 |   2 |             0 |
    | 201620 |    003 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201621 |    003 |            0 |   2 |   2 |   0 |   2 |             2 |
    | 201622 |    003 |            0 |   3 |   3 |   0 |   3 |             3 |
    | 201623 |    003 |            0 |   4 |   4 |   0 |   4 |             4 |
    | 201624 |    003 |            0 |   5 |   5 |   0 |   5 |             5 |
    | 201625 |    003 |           53 |   6 |   1 |   5 |   1 |             0 |
    | 201626 |    003 |           49 |   7 |   1 |   6 |   1 |             0 |
    | 201627 |    003 |           98 |   8 |   1 |   7 |   1 |             0 |
    | 201628 |    003 |           54 |   9 |   1 |   8 |   1 |             0 |
    | 201629 |    003 |           53 |  10 |   2 |   8 |   1 |             0 |
    | 201630 |    003 |          103 |  11 |   1 |  10 |   1 |             0 |
    | 201631 |    003 |           59 |  12 |   1 |  11 |   1 |             0 |
    | 201632 |    003 |           35 |  13 |   1 |  12 |   1 |             0 |
    | 201633 |    003 |            0 |  14 |   6 |   8 |   1 |             1 |
    | 201634 |    003 |            0 |  15 |   7 |   8 |   2 |             2 |
    | 201635 |    003 |            0 |  16 |   8 |   8 |   3 |             3 |
    | 201636 |    003 |            0 |  17 |   9 |   8 |   4 |             4 |
    | 201637 |    003 |           87 |  18 |   1 |  17 |   1 |             0 |
    | 201638 |    003 |          136 |  19 |   1 |  18 |   1 |             0 |
    | 201639 |    003 |           56 |  20 |   1 |  19 |   1 |             0 |
    | 201640 |    003 |           70 |  21 |   1 |  20 |   1 |             0 |
    | 201641 |    003 |           77 |  22 |   1 |  21 |   1 |             0 |
    | 201601 |    004 |            0 |   1 |   1 |   0 |   1 |             1 |
    | 201602 |    004 |            6 |   2 |   1 |   1 |   1 |             0 |
    | 201603 |    004 |            0 |   3 |   2 |   1 |   1 |             1 |
    | 201604 |    004 |            0 |   4 |   3 |   1 |   2 |             2 |
    +--------+--------+--------------+-----+-----+-----+-----+---------------+