2016-12-08 5 views
4

아래의 문제에 대한 최적의 쿼리를 작성하는 데 도움이 필요합니다. 내가 가지고있는 쿼리를 첨부했지만 리소스를 많이 활용하고 있습니다. 이하 TSQL - 그룹 및 섬 날짜

enter image description here

위 달성 가능 코드 논리이다. 동일하게하기위한 최적의 방법을 제안하십시오.

-- drop table #me 
create table #ME (memid int , EffectiveDate datetime , termdate datetime) 

Insert into #ME values ('123','3-Dec-16','10-Jan-17') 
Insert into #ME values ('123','11-Jan-17','6-Feb-17') 
Insert into #ME values ('123','7-Feb-17','5-Mar-17') 
Insert into #ME values ('123','8-Mar-17','15-Apr-17') 
Insert into #ME values ('123','16-Apr-17','24-May-17') 

--drop table #dim 
select * from #ME 
declare @StartDate datetime , @CutoffDate datetime 

select @StartDate= min(effectivedate),@CutoffDate = max(termdate) From #me where termdate<>'9999-12-31 00:00:00.000' 

SELECT d 
into #dim 
FROM 
(
    SELECT d = DATEADD(DAY, rn - 1, @StartDate) 
    FROM 
    (
    SELECT TOP (DATEDIFF(DAY, @StartDate, @CutoffDate)) 
     rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id]) 
    FROM sys.all_objects AS s1 
    CROSS JOIN sys.all_objects AS s2 
    -- on my system this would support > 5 million days 
    ORDER BY s1.[object_id] 
) AS x 
) AS y; 

--drop table #MemEligibilityDateSpread 

select MemID, D As DateSpread Into #MemEligibilityDateSpread From #Dim dim JOIN #me ME on dim.d between ME.effectivedate and me.termdate 

--drop table #DateClasified 

WITH CTE AS 
(
SELECT MEmID, 
     UniqueDate = DateSpread, 
     DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (PARTITION BY Memid ORDER BY Memid,DateSpread), DateSpread) 
    FROM #MemEligibilityDateSpread 
    GROUP BY Memid,DateSpread 
) 
--===== Now, if we find the MIN and MAX date for each DateGroup, we'll have the 
    -- Start and End dates of each group of contiguous daes. While we're at it, 
    -- we can also figure out how many days are in each range of days. 
SELECT Memid, 
     StartDate = MIN(UniqueDate), 
     EndDate = MAX(UniqueDate) 
    INTO #DateClasified 
    FROM cte 
    GROUP BY Memid,DateGroup 
    ORDER BY Memid,StartDate 

select ME.MemID,ME.EffectiveDate,ME.TermDate,DC.StartDate,DC.EndDate from #DateClasified dc join #me ME ON Me.MemID = dc.MemID 
     and (ME.EffectiveDate BETWEEN DC.StartDate AND DC.EndDate 
       OR ME.TermDate BETWEEN DC.StartDate AND DC.EndDate) 

답변

3

cte0 및 cte1에서 우리는 ad-hoc 탈리/달력 표를 만듭니다. 일단 우리가 그것을 가지고, 섬에 의해 계산하고 그룹화하는 작은 문제입니다.

현재, 집계가이 만일 (이십칠년)의 최대를 가지고 있지만, 당신은 쉽게 , 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 

편집을 추가하여 집계 테이블을 확장 할 수 있습니다 - 이제 압축 된 데이터 세트를 원한다면

내가 원격 서버에서 실행하면 3,691,363,210
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 
+0

내 로컬 컴퓨터에서 그것을 실행 한 작동 잘, 그것은 130 records.Haven't 어떤 일을 변경하지만 주위 생산, 다른 기계에서 서로 다른 출력을 생성 . 어떤 생각? 동일한 입력, 동일한 쿼리이지만 다른 출력 – vignesh

+0

CTE1을 temp로 만들어 실행했습니다. 이제 정상적으로 작동합니다. 왜 그것이 cte로 작동하지 않는지 어떤 아이디어? – vignesh

+0

@vignesh 왜 cte가 문제를 일으키는 지 알지 못합니다. 나 한테 이해가 안돼. –