连续日期范围内的最小和最大日期(按名称分组)

时间:2020-05-06 22:27:08

标签: sql sql-server gaps-and-islands

我有一个人的开始日期和结束日期的数据范围,我只想获取每个人的连续日期范围:

输入:

NAME | STARTDATE      | END DATE
--------------------------------------
MIKE | **2019-05-15** | 2019-05-16 
MIKE | 2019-05-17     | **2019-05-18**
MIKE | 2020-05-18     | 2020-05-19

预期的输出如下:

MIKE | **2019-05-15** | **2019-05-18** 
MIKE | 2020-05-18     | 2020-05-19

所以基本上每个人在每个连续周期的输出都是MIN和MAX。

感谢任何帮助。

我尝试了以下查询:

With N AS (   SELECT Name, StartDate, EndDate
       , LastStop = MAX(EndDate) 
                    OVER (PARTITION BY Name ORDER BY StartDate, EndDate 
                          ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)   FROM   Table  ), B AS (   SELECT Name, StartDate, EndDate
       , Block = SUM(CASE WHEN LastStop Is Null Then 1
                          WHEN LastStop < StartDate Then 1
                          ELSE 0
                    END)
                 OVER (PARTITION BY Name ORDER BY StartDate, LastStop)   FROM   N ) SELECT Name
     , MIN(StartDate) DateFrom
     , MAX(EndDate) DateTo FROM   B GROUP BY Name, Block ORDER BY Name, Block

但是它没有考虑连续期。显示相同的输入。

2 个答案:

答案 0 :(得分:1)

以下是使用临时统计表的示例

示例或dbFiddle

;with cte as (
Select A.[Name]
      ,B.D
      ,Grp  = datediff(day,'1900-01-01',D) - dense_rank() over (partition by [Name] Order by D)
 From  YourTable A
 Cross Apply ( 
                Select Top (DateDiff(DAY,StartDate,EndDate)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),StartDate) 
                 From  master..spt_values n1,master..spt_values n2 
             ) B

)
Select [Name]
      ,StartDate= min(D)
      ,EndDate  = max(D)
 From  cte
 Group By [Name],Grp

返回

Name    StartDate   EndDate
MIKE    2019-05-15  2019-05-18
MIKE    2020-05-18  2020-05-19

为了帮助实现可视化,CTE会生成以下内容

enter image description here

答案 1 :(得分:0)

这将为您带来相同的结果

    SELECT subquery.name,min(subquery.startdate),max(subquery.enddate1)
FROM (SELECT NAME,startdate,
      CASE WHEN EXISTS(SELECT yt1.startdate 
                       FROM t yt1 
                       WHERE yt1.startdate = DATEADD(day, 1, yt2.enddate) 
                       ) THEN null else yt2.enddate END as enddate1
      FROM t yt2) as subquery
GROUP by NAME, CAST(MONTH(subquery.startdate) AS VARCHAR(2)) + '-' + CAST(YEAR(subquery.startdate) AS VARCHAR(4))

对于CASE WHEN EXISTS,我指的是SQL CASE

对于按月份和年份分组,您可以看到此GROUP BY MONTH AND YEAR

DB_FIDDLE