TSQL - 群组和群岛日期

时间:2016-12-08 09:53:20

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

我需要帮助为下面的问题编写最佳查询。附上了我的查询,但它正在高度利用资源。

enter image description here

以下是实现上述逻辑的代码。请提出一些实现相同的最佳方法

{{1}}

1 个答案:

答案 0 :(得分:4)

在cte0和cte1中,我们创建了一个临时的计数/日历表。一旦我们有了这个,按岛计算和分组是一件小事。

目前,该计数最多为10,000天(27年),但您可以通过添加, cte0 N5

轻松扩展计数表
;with cte0(N)   as (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N))
     ,cte1(R,D) as (Select Row_Number() over (Order By (Select Null))
                          ,DateAdd(DD,-1+Row_Number() over (Order By (Select Null)),(Select MinDate=min(EffectiveDate) From  #ME)) 
                     From  cte0 N1, cte0 N2, cte0 N3, cte0 N4) 
Select MemID
      ,EffectiveDate 
      ,TermDate     
      ,SinceFrom = Min(EffectiveDate) over (Partition By Island)
      ,Tildate   = Max(TermDate) over (Partition By Island)
 From (
         Select *,Island = R - Row_Number() over (Partition By MemID Order by TermDate)
          From  #ME A
          Join  cte1 B on D Between EffectiveDate and TermDate
      ) A
 Group By MemID,Island,EffectiveDate,TermDate
 Order By 1,2

返回

MemID   EffectiveDate   TermDate    SinceFrom   Tildate 
123     2016-12-03      2017-01-10  2016-12-03  2017-03-05  
123     2017-01-11      2017-02-06  2016-12-03  2017-03-05  
123     2017-02-07      2017-03-05  2016-12-03  2017-03-05  
123     2017-03-08      2017-04-15  2017-03-08  2017-05-24  
123     2017-04-16      2017-05-24  2017-03-08  2017-05-24  
  

编辑 - 现在,如果您需要压缩数据集

Select MemID
      ,EffectiveDate = Min(EffectiveDate)
      ,TermDate      = Max(TermDate) 
 From (
         Select *,Island = R - Row_Number() over (Partition By MemID Order by TermDate)
          From  #ME A
          Join  cte1 B on D Between EffectiveDate and TermDate
      ) A
 Group By MemID,Island
 Order By 1,2

返回

MemID   EffectiveDate   TermDate
123     2016-12-03      2017-03-05
123     2017-03-08      2017-05-24