代码之家  ›  专栏  ›  技术社区  ›  Kashyap MNVL

递归地遍历SQL表并根据开始和结束日期查找间隔

  •  0
  • Kashyap MNVL  · 技术社区  · 6 年前

    我有一个包含employeeid、StartDateTime和EndDatetime的SQL表,如下所示:

    CREATE TABLE Sample
    (
        SNO INT,
        EmployeeID NVARCHAR(10),
        StartDateTime DATE,
        EndDateTime DATE
    )
    
    INSERT INTO Sample
    VALUES
    ( 1, 'xyz', '2018-01-01', '2018-01-02' ), 
    ( 2, 'xyz', '2018-01-03', '2018-01-05' ), 
    ( 3, 'xyz', '2018-01-06', '2018-02-01' ), 
    ( 4, 'xyz', '2018-02-15', '2018-03-15' ), 
    ( 5, 'xyz', '2018-03-16', '2018-03-19' ),
    ( 6, 'abc', '2018-01-16', '2018-02-25' ),
    ( 7, 'abc', '2018-03-08', '2018-03-19' ),
    ( 8, 'abc', '2018-02-26', '2018-03-01' )
    

    EmployeeID  |  StartDateTime  |  EndDateTime
    ------------+-----------------+---------------
       xyz      |  2018-01-01     |  2018-02-01
       xyz      |  2018-02-15     |  2018-03-19
       abc      |  2018-01-16     |  2018-03-01
       abc      |  2018-03-08     |  2018-03-19
    

    基本上,我希望递归地查看每个员工的记录,并对开始日期和结束日期的连续性进行日期挖掘,并生成一组连续的日期记录。

    SELECT * 
    FROM dbo.TestTable T1 
    LEFT JOIN dbo.TestTable t2 ON t2.EmpId = T1.EmpId
    WHERE t1.EndDate = DATEADD(DAY, -1, T2.startdate)
    

    看看我能不能从输出中破译一些东西,寻找一种模式。后来意识到,使用上述方法,我需要多次连接同一个表以获得所需的输出。

    此外,还有一种情况是可能有多个员工记录,所以我需要指导如何有效地获得所需的输出。

    非常感谢您的帮助。

    2 回复  |  直到 6 年前
        1
  •  2
  •   TomC    6 年前

    ;with cte as (
        select EmployeeID, StartDateTime, EndDateTime 
        from sample s
        union all
        select CTE.EmployeeID, CTE.StartDateTime, s.EndDateTime
        from sample s
        join cte on cte.EmployeeID=s.EmployeeID and s.StartDateTime=dateadd(d,1,CTE.EndDateTime)
    )
    select EmployeeID, Min(StartDateTime) as StartDateTime, EndDateTime from (
        select EmployeeID, StartDateTime, Max(EndDateTime) as EndDateTime from cte
        group by EmployeeID, StartDateTime
    ) q group by EmployeeID, EndDateTime
    
        2
  •  1
  •   Serkan Arslan    6 年前

    你可以用这个。

    WITH T AS (
        SELECT  S1.SNO, 
                S1.EmployeeID, 
                S1.StartDateTime, 
                ISNULL(S2.EndDateTime, S1.EndDateTime) EndDateTime,
                ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId ORDER BY S1.StartDateTime) 
                    - ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId, CASE WHEN S2.StartDateTime IS NULL THEN 0 ELSE 1 END  ORDER BY S1.StartDateTime ) RN,
                ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId, ISNULL(S2.EndDateTime, S1.EndDateTime) ORDER BY S1.EmployeeId, S1.StartDateTime) RN_END
        FROM Sample S1
            LEFT JOIN Sample S2 ON DATEADD(DAY,1,S1.EndDateTime) = S2.StartDateTime
    )
    SELECT EmployeeID,  MIN(StartDateTime) StartDateTime,MAX(EndDateTime) EndDateTime FROM T
    WHERE RN_END = 1
    GROUP BY EmployeeID, RN
    ORDER BY EmployeeID DESC, StartDateTime
    

    结果:

    EmployeeID StartDateTime EndDateTime
    ---------- ------------- -----------
    xyz        2018-01-01    2018-02-01
    xyz        2018-02-15    2018-03-19
    abc        2018-01-16    2018-03-01
    abc        2018-03-08    2018-03-19