2016-12-08 4 views
4

Ich brauche eine Hilfe beim Schreiben einer optimalen Abfrage für das folgende Problem. Ich habe die Frage, die ich bei mir habe, angefügt, aber es nutzt Ressourcen.TSQL - Gruppen und Inseln Daten

enter image description here

Unten finden Sie den obigen Code Logik sagte zu erreichen. Bitte legen nahe, eine optimale Art und Weise die gleiche

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

Antwort

3

In cte0 und CTE1 zu erreichen, schaffen wir eine Ad-hoc-tally/Kalender-Tabelle. Sobald wir das haben, ist es eine kleine Angelegenheit, nach Island zu berechnen und zu gruppieren.

Derzeit ist die Tally ist, hat ein Maximum von 10.000 Tage (27 Jahre), aber man kann die Tally-Tabelle leicht erweitern durch Hinzufügen , 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 

Returns

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 

bearbeiten - Wenn Sie jetzt einen komprimierten Datensatz wünschen

Returns

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

Ich habe lief es in meinem lokalen Rechner funktioniert gut, wenn ich in der Remote-Server laufen sie produziert rund 130 records.Haven't irgend etwas geändert, aber in verschiedenen Maschinen produziert es verschiedene Ausgänge . Irgendeine Idee? Gleicher Input, gleiche Query, aber unterschiedliche Ausgabe – vignesh

+0

CTE1 als Temp & Ran gemacht, funktioniert jetzt gut. Irgendeine Idee, warum es nicht als cte funktioniert? – vignesh

+0

@vignesh Keine Ahnung, warum der Cte ein Problem verursacht. Für mich ergibt das keinen Sinn. –

Verwandte Themen