【问题标题】:Count previous row only if > 2 days later仅当 > 2 天后才计算前一行
【发布时间】:2018-08-03 03:57:46
【问题描述】:

在使用 Studio 的 SQL Server 2012 中:我需要显示不同客户端编号 (CN) 的结果以重新输入,按类型分组,如下所示:

Type    CountOfCN    
5        1  
10       3  

只有一个 RE 条目计入(ENTRY_NO 1 从不计入),并且它必须在该客户编号的上一个条目结束后 2 天以上。所以基本上 ENTRY_NO 1 不算数。如果开始日期比 ENTRY_NO 1 的结束日期晚 2 天以上,则 ENTRY_NO 2 计算在内,依此类推,ENTRY_NO 3、4、5。

我在创建表时通过执行 ROW_NUMBER 函数获得了 ENTRY_NO。我不知道如何创建一个 datediff 或 dateadd 函数 (?) 来查看前一行的 enddate 并用我的 startdate 为每个 CN 计算它?

这是我的桌子:

CN    STARTDATE   ENDDATE    TYPE  ENTRY_NO  
1     1/1/2018    1/20/2018  10    1
1     1/21/2018   1/30/2018   5    2
1     2/3/2018    NULL       10    3
2     1/1/2018    1/20/2018  10    1
2     1/27/2018   1/30/2018  10    2
3     1/1/2018    1/20/2018   5    1
3     1/27/2018   1/30/2018  10    2
3     2/10/2018   2/20/2018   5    3
4     1/7/2018    1/30/2018   5    1
5     1/27/2018   1/30/2018   5    1
5     1/31/2018   NULL        5    2

所以应该在结果中的行是 ENTRY_NO 2 代表 CN 1,ENTRY_NO 2 代表 CN 2,ENTRY_NO 2 和 3 代表 CN 3。

只有最后一个条目可能/可能没有 NULL 结束日期

【问题讨论】:

  • 用您正在使用的数据库标记您的问题。而且我看不出结果与样本数据有什么关系。
  • 我解释了结果与我表下的样本数据有什么关系
  • 当开始日期仅比前一个结束日期早一天时,为什么 Entry_no 2 会计入 CN 1? (1/20 - 1/21)
  • 它不会,那是一个错字(感谢在这里格式化所需的向后弯曲)。那应该是 CN 1 的第 3 项,而不是 2。感谢您指出这一点。

标签: sql sql-server sql-server-2012


【解决方案1】:

使用 LAG 窗口函数可以获得上一个结束日期。

SELECT * 
FROM
(
  SELECT * , 
   LAG(ENDDATE) OVER (PARTITION BY CN ORDER BY STARTDATE) AS prevEndDate
  FROM yourtable
) q
WHERE DATEDIFF(d, prevEndDate, STARTDATE) > 2
AND ENDDATE IS NOT NULL

【讨论】:

  • 正是我想要的。有用!非常感谢!我以前从未使用过 LAG。我被要求给子查询起别名。
  • 你能把AND ENDDATE IS NOT NULL移动到子查询吗?
  • @JohnyL 可能。但是如果她的数据在最后一个 CN 中只有 NULL enddates,那么在外部查询中只需要 1 个 WHERE 子句。
【解决方案2】:

根据您要强制执行的条件将表内部连接到自身:

  • 不能是Entry_No1
  • 一侧的Entry_No 比另一侧大一
  • 上一个条目必须早于 2 天
  • 连接的两边都有相同的CN

使用该联接创建 CTE 或派生表,然后从中选择,按 Type 分组并获取 COUNT(*)

【讨论】:

    【解决方案3】:

    所以这最终比我最初想象的更复杂,但它就在这里......

    您可以在 SSMS 中运行此示例。

    创建一个与您上面的定义匹配的表变量:

    DECLARE @data TABLE ( CN INT, STARTDATE DATETIME, ENDDATE DATETIME, [TYPE] INT, ENTRY_NO INT );
    

    插入给定的数据:

    INSERT INTO @data ( CN, STARTDATE, ENDDATE, [TYPE], ENTRY_NO ) VALUES   
    ( 1, '1/1/2018', '1/20/2018', 10, 1 )
    , ( 1, '1/21/2018', '1/30/2018', 5, 2 )
    , ( 1, '2/3/2018', NULL, 10, 3 )
    , ( 2, '1/1/2018', '1/20/2018', 10, 1 )
    , ( 2, '1/27/2018', '1/30/2018', 10, 2 )
    , ( 3, '1/1/2018', '1/20/2018', 5, 1 )
    , ( 3, '1/27/2018', '1/30/2018', 10, 2 )
    , ( 3, '2/10/2018', '2/20/2018', 5, 3 )
    , ( 4, '1/7/2018', '1/30/2018', 5, 1 )
    , ( 5, '1/27/2018', '1/30/2018', 5, 1 )
    , ( 5, '1/31/2018', NULL, 5, 2 );
    

    确认插入的数据:

    +----+-------------------------+-------------------------+------+----------+
    | CN |        STARTDATE        |         ENDDATE         | TYPE | ENTRY_NO |
    +----+-------------------------+-------------------------+------+----------+
    |  1 | 2018-01-01 00:00:00.000 | 2018-01-20 00:00:00.000 |   10 |        1 |
    |  1 | 2018-01-21 00:00:00.000 | 2018-01-30 00:00:00.000 |    5 |        2 |
    |  1 | 2018-02-03 00:00:00.000 | NULL                    |   10 |        3 |
    |  2 | 2018-01-01 00:00:00.000 | 2018-01-20 00:00:00.000 |   10 |        1 |
    |  2 | 2018-01-27 00:00:00.000 | 2018-01-30 00:00:00.000 |   10 |        2 |
    |  3 | 2018-01-01 00:00:00.000 | 2018-01-20 00:00:00.000 |    5 |        1 |
    |  3 | 2018-01-27 00:00:00.000 | 2018-01-30 00:00:00.000 |   10 |        2 |
    |  3 | 2018-02-10 00:00:00.000 | 2018-02-20 00:00:00.000 |    5 |        3 |
    |  4 | 2018-01-07 00:00:00.000 | 2018-01-30 00:00:00.000 |    5 |        1 |
    |  5 | 2018-01-27 00:00:00.000 | 2018-01-30 00:00:00.000 |    5 |        1 |
    |  5 | 2018-01-31 00:00:00.000 | NULL                    |    5 |        2 |
    +----+-------------------------+-------------------------+------+----------+
    

    根据您的业务规则运行 SQL 以获取类型计数:

    • ENTRY_NO 必须大于 1
    • 当前的 CN ENDDATE 必须比上一个 ENDDATE 晚 2 天

    T-SQL:

    SELECT
        [TYPE], COUNT( DISTINCT CN ) AS ClientCount
    FROM @data
    WHERE
        CN IN (
    
            SELECT DISTINCT CN FROM (
    
                SELECT
                    dat.CN
                    , dat.ENTRY_NO
                    , dat.[TYPE]
                    , DATEDIFF( DD
                        , LAG( ENDDATE, 1, NULL ) OVER ( PARTITION BY CN ORDER BY CN, ENDDATE ) -- gets enddate for previous CN entry
                        , ENDDATE
                    ) AS DayDiff
                FROM @data dat
    
            ) AS Clients
            WHERE
                Clients.ENTRY_NO >= 2
                AND Clients.DayDiff > 2
        )
    GROUP BY
        [TYPE]
    ORDER BY
        [TYPE];
    

    返回:

    +------+-------------+
    | TYPE | ClientCount |
    +------+-------------+
    |    5 |           2 |
    |   10 |           3 |
    +------+-------------+
    

    快速查看 IN 子查询会发现 CN 1、2 和 3 将包含在“TYPE”计数中。

    SELECT
        dat.CN
        , dat.ENTRY_NO
        , dat.[TYPE]
        , DATEDIFF( DD
            , LAG( ENDDATE, 1, NULL ) OVER ( PARTITION BY CN ORDER BY CN, ENDDATE ) -- gets enddate for previous CN entry
            , ENDDATE
        ) AS DayDiff
    FROM @data dat
    ORDER BY
        dat.CN, dat.ENTRY_NO;
    
    +----+----------+------+---------+
    | CN | ENTRY_NO | TYPE | DayDiff |
    +----+----------+------+---------+
    |  1 |        1 |   10 | NULL    |
    |  1 |        2 |    5 | 10      |
    |  1 |        3 |   10 | NULL    |
    |  2 |        1 |   10 | NULL    |
    |  2 |        2 |   10 | 10      |
    |  3 |        1 |    5 | NULL    |
    |  3 |        2 |   10 | 10      |
    |  3 |        3 |    5 | 21      |
    |  4 |        1 |    5 | NULL    |
    |  5 |        1 |    5 | NULL    |
    |  5 |        2 |    5 | NULL    |
    +----+----------+------+---------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-29
      • 1970-01-01
      • 2023-04-04
      • 2020-05-09
      • 1970-01-01
      • 2011-11-23
      • 2022-07-08
      • 2022-07-08
      相关资源
      最近更新 更多