2016-07-27 14 views
1

Edited alle Fälle abzudeckenSplit Zeilen basierend auf Termine und Aktualisierung Start- und Ziel überlappende Daten

Ich bin relativ neu in SQL (SQL Server 2008), und ich habe, wie unten die Problemstellung. Die Daten in der Tabelle können überlappende Zeitdauern enthalten, aber dies muss ausgesondert werden (Below Beispieldatensatz)

Die Daten in Tabelle ist wie folgt:

Column 1 |Column 2 |StartTime |EndTime |Factor 

    A   |B   |Jan 1  |Jun 30  |0.7 
    A   |B   |Feb 1  |September 30|0.3 
    A   |B   |Mar 1  |August 31 |0.2 

Die gewünschte Ausgabe ist wie folgt:

Column 1 |Column 2 |StartTime |EndTime |Factor 
    A   |B   |Jan 1 |Jan 31 |0.7 
    A   |B   |Feb 1  |Feb 28 |1.0 
    A   |B   |Mar 1  |Jun 30 |1.2 
    A   |B   |Jul 1  |August 31 |0.5 
    A   |B   |Sept 1 |Sept 30 |0.3 

Voraussetzung ist, dass, wenn Spalte 1 und Spalte 2 gleich und die Daten überlappen, soll der Faktor zusammengefasst werden, und ein neuer Datensatz sollte mit einer neuen Start- und Endzeit erstellt werden, so dass es eine Kontinuität.

Die Start- und Endzeit sind im DATETIME-Format.

Ich versuchte, Self-Joins zu verwenden, erreichte aber nirgendwo. Hat jemand irgendwelche Vorschläge?

+0

Wegwerfen es ist die gleiche Ausgabe und Daten präsentiert .. Details? –

+0

Wie ist Mar June Faktor cacluated – TheGameiswar

+0

Wie werden Ihre Start- und Endzeiten gehalten? Sind sie Daten oder nur Text? Wenn es Text ist, wird dort ein Jahr gehalten? Ich glaube, der Fragesteller möchte die Faktoren zusammenfassen, wenn es eine Überschneidung gibt. Wenn Sie also eine Tabelle mit Monaten, 1-12, hätten, könnten Sie alle Faktoren, die in diesen Bereich fallen, summieren (obwohl die angezeigten Daten Text für Monatsnamen verwenden). Das Rekombinieren von Summen für 1-12 ist ein "Insel" -Problem, das mit WITH, row_number, einem Self-Join zur vorherigen Zeile und der Erkennung von Änderungspunkten gelöst werden kann. – Cato

Antwort

0
DECLARE @MD AS int; 

SELECT @MD = MAX(YEAR(a2.STARTTIME) * 100 + MONTH(a2.ENDTIME)) FROM ashtable a2; 

WITH MTHS AS (
        SELECT MIN(YEAR(STARTTIME) * 100 + MONTH(STARTTIME)) TheMonth FROM ashtable 
        UNION ALL 
        SELECT TheMonth + 1 FROM MTHS WHERE TheMonth < @MD 
       ), 
    ALLMONTHS AS 
       (
        select a.Column1,a.column2,m.TheMonth, SUM(FACTOR) f from mths m 
           LEFT JOIN 
            ashtable a 
             ON m.TheMonth >= YEAR(a.STARTTIME) * 100 + MONTH(a.STARTTIME) 
             AND 
             m.TheMonth <= YEAR(a.ENDTIME) * 100 + MONTH(a.ENDTIME) 
         GROUP BY a.Column1,a.column2, m.TheMonth 
       ), 
    RNS AS 
       (SELECT a.Column1,a.column2,a.TheMonth, a.f, a.f - COALESCE(b.f, -99999999.99) dif FROM ALLMONTHS a 
             LEFT JOIN ALLMONTHS b ON a.TheMonth = b.TheMonth + 1 AND a.column1=b.column1 and a.column2=b.column2), 
    ISLANDS AS (
       select a.Column1,a.column2,a.TheMonth, 
         MIN(b.TheMonth) MonthEnd, 
         MIN(A.f) Factor 
           from RNS a 
            LEFT JOIN RNS b ON a.column1=b.column1 and a.column2=b.column2 and b.TheMonth > a.TheMonth AND b.f <> a.f WHERE a.dif <> 0 
           GROUP BY a.column1,a.column2,a.TheMonth 
       )    
    SELECT Column1,column2,dateadd(month, (themonth - 1) % 100, 
      DateADD(year,(Themonth)/100 - 1900, 0)) s, 
      dateadd(day,-1,dateadd(month, (themonth) % 100, 
      DateADD(year,(Themonth)/100 - 1900, 0))) e, factor FROM ISLANDS order by column1,column2,s 

meiner Ausgabe (einschließlich einer Testreihe für verschiedene Spaltenschlüssel)

Column1 column2 s      e      factor 
---------- ---------- ----------------------- ----------------------- ------- 
A   B   2016-01-01 00:00:00.000 2016-01-31 00:00:00.000 0.7 
A   B   2016-02-01 00:00:00.000 2016-02-29 00:00:00.000 1.0 
A   B   2016-03-01 00:00:00.000 2016-03-31 00:00:00.000 1.2 
A   B   2016-07-01 00:00:00.000 2016-07-31 00:00:00.000 0.5 
A   B   2016-09-01 00:00:00.000 2016-09-30 00:00:00.000 0.3 
A   C   2016-01-01 00:00:00.000 2016-01-31 00:00:00.000 99.0 

hier ist eine modifizierte Version, meine gescheiterten Ideen repräsentieren Jahr Monat als Integer

DECLARE @MD AS datetime; 

SELECT @MD = MAX(endtime) FROM ashtable a2; 

WITH MTHS AS (
        SELECT MIN(STARTTIME) TheMonth FROM ashtable 
        UNION ALL 
        SELECT dateadd(month,1,TheMonth) TheMonth FROM MTHS WHERE TheMonth < @MD 
       ), 

    ALLMONTHS AS 
       (
        select a.Column1,a.column2,m.TheMonth, SUM(FACTOR) f from mths m 
           LEFT JOIN 
            ashtable a 
             ON m.TheMonth >= a.starttime 
             AND 
             m.TheMonth < a.endtime 
         GROUP BY a.Column1,a.column2, m.TheMonth 
       ), 
    RNS AS 
       (SELECT a.Column1,a.column2,a.TheMonth, a.f, a.f - COALESCE(b.f, -99999999.99) dif FROM ALLMONTHS a 
             LEFT JOIN ALLMONTHS b ON a.TheMonth = dateadd(month,1,b.TheMonth) AND a.column1=b.column1 and a.column2=b.column2), 
    ISLANDS AS (
       select a.Column1,a.column2,a.TheMonth,dq2.lastmonth,a.f factor 
        from RNS a 
        CROSS APPLY 
         (SELECT TOP 1 * FROM (SELECT 1 as ord, b.TheMonth lastmonth FROM RNS b WHERE a.Column1 = b.column1 and a.column2=b.column2 and b.themonth>a.themonth and a.f <> b.f 
         union SELECT 2 as ord, dateadd(month,1,max(c.themonth)) lastmonth from rns c where a.Column1 = c.column1 and a.column2=c.column2) dq ORDER BY DQ.ord) dq2 
         where a.dif<>0 
         --MIN(b.TheMonth) MonthEnd, 
         --MIN(A.f) Factor 
         --  from RNS a 
         --   LEFT JOIN RNS b ON a.column1=b.column1 and a.column2=b.column2 and b.TheMonth > a.TheMonth AND b.f <> a.f where a.dif<>0 
         --  GROUP BY a.column1,a.column2,a.TheMonth 
       ) 


    SELECT Column1,column2,themonth, dateadd(day,-1,lastmonth), 
      factor FROM ISLANDS order by column1,column2,themonth 
+0

Die Lösung sieht gut aus, außer es scheint keine Kontinuität zu geben, dh , sollte die dritte Reihe idealerweise 2016-06-30 enden. Ich werde den Code nochmal durchgehen und sehen, ob das geändert werden kann, danke für den Start. –

+0

es braucht Arbeit - ich untersuche es – Cato