2016-10-12 3 views
1

Ich habe ein Problem, bei dem ich die Daten mehrerer Zeilen vergleichen muss. Die Anforderung besteht darin, dass die Daten nach "Region/Gebiet" -Kombination mit dem niedrigsten "Startdatum" und dem höchsten "Enddatum" gruppiert werden müssen, WENN zwischen dem vorherigen "Enddatum" und dem nächsten "Startdatum" eine Lücke von mehr als 1 Tag besteht.SQL 2012 Daten über mehrere Zeilen hinweg vergleichen

Das 'StartDate' ist immer der erste des Monats und das 'EndDate' ist immer der letzte Tag des Monats.

eine vereinfachte Tabelle als solche Gegeben:

Region | Area | StartDate | EndDate 
-------|------|---------------|------------- 
    A | 1 | 01/01/2016 | 03/31/2016 
    A | 1 | 04/01/2016 | 05/31/2016 
    A | 1 | 07/01/2016 | 09/30/2016 
    A | 1 | 10/01/2016 | 01/31/2017 
    A | 1 | 02/01/2017 | 12/31/2017 
    B | 2 | 01/01/2016 | 04/30/2016 
    B | 2 | 05/01/2016 | 09/30/2016 
    A | 4 | 01/01/2016 | 05/31/2016 
    A | 4 | 06/01/2016 | 12/31/2016 

ich die Ergebnisse brauchen so etwas wie folgt aussehen:

Region | Area | StartDate | EndDate 
-------|------|--------------|----------- 
    A | 1 | 01/01/2016 | 05/31/2016 
    A | 1 | 07/01/2016 | 12/31/2017 
    B | 2 | 01/01/2016 | 09/30/2016 
    A | 4 | 01/01/2016 | 12/31/2016 

I GROUP BY mit MIN und MAX Daten versucht, aber ich kann nicht scheinen zu verstehe die Logik richtig.

Alle Gedanken oder Vorschläge würden sehr geschätzt werden.

Antwort

1

Dies scheint ein Dateninselproblem zu sein. Sie können die in SQL Server 2012 eingeführten Fensterfunktionen verwenden. Mithilfe der Windowing-Funktion LAG können Sie bestimmen, ob die Enddatumsdaten Ihrer letzten Datensätze eine Lücke größer als ein Tag mit dem aktuellen Datum von datetime für Datensätze haben. Als Nächstes können Sie die Klausel SUM OVER verwenden, um eine Gruppierungs-ID für jede Ihrer Dateninseln zu generieren.

DECLARE @SourceData TABLE 
(
    Region   NVARCHAR(10) 
    ,Area   INT 
    ,StartDate  DATETIME 
    ,EndDate  DATETIME 
); 

INSERT INTO @SourceData 
VALUES 
('A', 1, '01/01/2016', '03/31/2016'), 
('A', 1, '04/01/2016', '05/31/2016'), 
('A', 1, '07/01/2016', '09/30/2016'), 
('A', 1, '10/01/2016', '01/31/2017'), 
('A', 1, '02/01/2017', '12/31/2017'), 
('B', 2, '01/01/2016', '04/30/2016'), 
('B', 2, '05/01/2016', '09/30/2016'), 
('A', 4, '01/01/2016', '05/31/2016'), 
('A', 4, '06/01/2016', '12/31/2016'); 

;WITH CTE_DataIslands -- First CTE determine the start of each new data island 
AS 
(
    SELECT   Region 
        ,Area 
        ,StartDate 
        ,EndDate 
        ,(
         CASE 
          WHEN DATEADD(DAY, 1, LAG(EndDate, 1) OVER (PARTITION BY Region, Area ORDER BY StartDate ASC)) < (StartDate) THEN 1 -- If prev record's end date + 1 day is not equal to current record's start date then it is the start of a new data island. 
          ELSE 0 
         END 
        ) AS [IsNewDataIsland] 
    FROM   @SourceData 
) 
, CTE_GenerateGroupingID 
AS 
(
    SELECT Region 
      ,Area 
      ,StartDate 
      ,EndDate 
      ,SUM([IsNewDataIsland]) OVER (PARTITION BY Region, Area ORDER BY StartDate ASC ROWS UNBOUNDED PRECEDING) AS GroupingID -- Create a running total of the IsNewDataIsland column this will create a grouping id we can now group on 
    FROM CTE_DataIslands 
) 
SELECT  Region 
      ,Area 
      ,MIN(StartDate) AS StartDate 
      ,MAX(EndDate) AS StartDate 
FROM  CTE_GenerateGroupingID 
GROUP BY Region, Area, GroupingID 
+0

Vielen Dank, hatte ich die Teile scheine ich nur konnte sie nicht –

+0

zusammen zu bekommen @JeffMartinez keine Sorgen, froh, dass es für Sie –

+0

Eine Follow-up-Frage gearbeitet - wenn es eine dritte Datumsspalte war, sagen 'ChangeDate', ich brauche nur den MAX-Wert für jede Gruppierung; wie schließt du das ein? Wenn ich versuche, die Ergebnisse zu erhöhen, setzte ich –

Verwandte Themen