仅在> 2天后才计算上一行

时间:2018-08-02 17:54:44

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

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

Type    CountOfCN    
5        1  
10       3  

仅重新输入计数(ENTRY_NO 1从不计数),并且必须在该客户编号的上一个条目结束之后超过2天。因此,基本上ENTRY_NO 1不计算在内。 ENTRY_NO 2计算开始日期是否比ENTRY_NO 1的结束日期晚2天以上,依此类推,例如ENTRY_NO 3、4、5。

创建表时,我通过执行ROW_NUMBER函数获得了ENTRY_NO。我不知道如何创建datediff或dateadd函数(?)来查看上一行的结束日期,并使用每个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

因此,结果中的行应为CN 1的ENTRY_NO 2,CN 2的ENTRY_NO 2,CN 3的ENTRY_NO 2&3。

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

  • 不能为Entry_No 1
  • 一侧的Entry_No比另一侧要大
  • 以前的条目必须早于2天
  • 联接的两端具有相同的CN

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

答案 2 :(得分:0)

所以这最终比我最初想象的要复杂得多,但是在这里...

您可以在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子查询,就会发现在“ TYPE”计数期间将包含CN 1、2和3。

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    |
+----+----------+------+---------+