2016-03-22 6 views
2

Ich möchte in einem aufsteigenden Min- und Max wählen/order Serie absteigend wenn Serie der Daten, umGruppierung Ergebnis Min/Max in einer Bruch Serie auf-/absteigend in SQL Teil 2

nähmen bricht Ich habe Daten in einem um von Datetime:

LogDate  StartValue EndValue Multiplier DiffValue 
2016-02-08 7661.25 7677.62  6.94  16.37 
2016-02-09 7677.62 7693.02  6.94  15.4 
2016-02-10 7693.02 7709.82  6.94  16.8 
2016-02-11 7709.82 7727.08  6.94  17.26 
2016-02-12 7727.08 7740.93  6.94  13.85 
2016-02-13 3.02  12.22  6.94  9.2 
2016-02-14 12.22  20.73  6.94  8.51 
2016-02-15 20.73  37.04  6.94  16.31 
2016-02-16 37.04  52.56  7   15.52 
2016-02-17 52.56  67.82  7   15.26 
2016-02-18 67.82  83.66  7   15.84 
2016-02-19 83.66  98.77  7   15.11 
2016-02-20 98.77  108.37  7   9.61 

und ich will das Ergebnis wie:

LogDateMin LogDateMax StartValue EndValue Multiplier SumOfDiffValue 
2016-02-08 2016-02-12 7661.25  7740.93  6.94  79.68 
2016-02-13 2016-02-15 3.02  37.04  6.94  34.02 
2016-02-16 2016-02-20 37.04  108.37  7   71.34 

hier ich das Ergebnis von Multiplier bin Gruppierung auch und immer Summe von deffValue

Wie können wir das

Bitte helfen

+1

Hallo, wie haben Sie 3 Reihen gt während das Ergebnis durch Multiplier Gruppierung. (Verfügbare Werte nur 6.94 und 7) –

+0

Auch ich muss Ergebnis gruppieren, wo StartValue/EndValue zurückgesetzt/Down von Prev Wert – Abhinandan

+1

Welche Version von SQL Server? –

Antwort

1

@Joachim schlug mich dazu (diese Antwort ist viel eleganter als meins), aber ich poste meine Variation trotzdem.

Edit: Eine sehr hacky Fix für den Fehler hervorgehoben in den Kommentaren :)

CREATE TABLE #Test (
    LogDate DATE, 
    StartValue DECIMAL(6,2), 
    EndValue DECIMAL(6,2), 
    Multiplier DECIMAL(3,2), 
    DiffValue DECIMAL(4,2) 
); 

INSERT INTO #Test(
    LogDate 
    ,StartValue 
    ,EndValue 
    ,Multiplier 
    ,DiffValue 
) 
VALUES  
    ('2016-02-08', 7661.25, 7677.62,  6.94,  16.37), 
    ('2016-02-09', 7677.62, 7693.02,  6.94,  15.4), 
    ('2016-02-10', 7693.02, 7709.82,  6.94,  16.8), 
    ('2016-02-11', 7709.82, 7727.08,  6.94,  17.26), 
    ('2016-02-12', 7727.08, 7740.93,  6.94,  13.85), 
    ('2016-02-13', 3.02,  12.22,  6.94,   9.2), 
    ('2016-02-14', 12.22,  20.73,  6.94,   8.51), 
    ('2016-02-15', 20.73,  37.04,  6.94,  16.31), 
    ('2016-02-16', 37.04,  52.56,  7,   15.52), 
    ('2016-02-17', 52.56,  67.82,  7,   15.26), 
    ('2016-02-18', 67.82,  83.66,  7,   15.84), 
    ('2016-02-19', 83.66,  98.77,  7,   15.11), 
    ('2016-02-20', 98.77,  108.37,  7,   9.61), 
    --Extra data 
    ('2016-02-21', 120,  150,   6.94,  30), 
    ('2016-02-22', 150,  180,   6.94,  30), 
    ('2016-02-24', 150,  180,   7,   30), 
    ('2016-02-25', 180,  200,   7,   30); 


WITH A AS(
    SELECT *, 
     CASE WHEN 
      StartValue < LAG(StartValue) OVER (PARTITION BY Multiplier ORDER BY LogDate) 
      OR DATEADD(DAY, -1, LogDate) > LAG(LogDate) OVER (PARTITION BY Multiplier ORDER BY LogDate) 
     THEN 1 ELSE 0 END AS grp 
    FROM #Test 
) 
,B AS(
    SELECT *, 
    SUM(grp) OVER (PARTITION BY A.Multiplier ORDER BY A.LogDate ROWS UNBOUNDED PRECEDING) SUM FROM A 
) 
,C AS (
    SELECT *, 
    DENSE_RANK() OVER (ORDER BY (CONVERT(VARCHAR(8), Multiplier)+' '+CONVERT(VARCHAR(1),sum))) rnk 
    FROM B 
) 
SELECT MIN(LogDate) LogDateMin 
    ,MAX(LogDate) LogDateMax 
    ,MIN(StartValue) StartValue 
    ,MAX(EndValue) EndValue 
    ,MIN(Multiplier) Multiplier 
    ,SUM(DiffValue) SumOfDiffValue 
FROM C GROUP BY Rnk 


LogDateMin LogDateMax StartValue        EndValue        Multiplier        SumOfDiffValue 
---------- ---------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- 
2016-02-08 2016-02-12 7661.25         7740.93         6.94         79.68 
2016-02-13 2016-02-15 3.02         37.04         6.94         34.02 
2016-02-21 2016-02-22 120.00         180.00         6.94         60.00 
2016-02-16 2016-02-20 37.04         108.37         7.00         71.34 
2016-02-24 2016-02-25 150.00         200.00         7.00         60.00 
+0

Eine Sache, die Sie vielleicht beheben möchten, wenn Sie eine Zeile für 2016-02-21 mit Multiplikator 6.94 hinzufügen (und einen größeren Startwert als 108.37), wird es mit dem Bereich ab dem 13. zusammenfassen und den Bereich beginnend überlappen am 16.. Ich nehme an, es sollte nicht (ich würde eine SQLFiddle hinzufügen, aber SQL Server 2014 scheint dort atm gebrochen) –

+0

[SQLfiddle] (http://sqlfiddle.com/#!6/9eecb7/6643), beachten Sie, dass die 21. sollte wohl eine eigene Gruppe sein. –

+0

Danke @joachim Ich werde es mir ansehen –

3

für SQL Server 2012 und bis erreichen, können Sie LAG verwenden, um die Änderungen und Gruppe durch, um das herauszufinden. Dies ist ein Weg;

WITH cte AS (
    SELECT LogDate, StartValue, EndValue, Multiplier, DiffValue, 
     LAG(EndValue) OVER (ORDER BY LogDate) OldEndValue, 
     LAG(Multiplier) OVER (ORDER BY LogDate) OldMultiplier 
    FROM myTable 
), cte2 AS (
    SELECT LogDate, StartValue, EndValue, Multiplier, DiffValue, 
    SUM(CASE WHEN OldEndValue > StartValue OR Multiplier <> OldMultiplier 
      THEN 1 ELSE 0 END) OVER (ORDER BY LogDate) grp 
    FROM cte 
) 
SELECT MIN(LogDate) LogDateMin, MAX(LogDate) LogDateMax, MIN(StartValue) StartValue, 
     MAX(EndValue) EndValue, MAX(Multiplier) Multiplier, SUM(DiffValue) DiffValue 
FROM cte2 
GROUP BY grp 
ORDER BY MIN(LogDate); 

Die erste CTE kommt noch hinzu, den vorherigen Wert von EndValue und Multiplier zu jeder Zeile.

Der zweite CTE führt eine laufende Summe über eine case-Anweisung aus, die die gewünschten Änderungen erkennt.

Die Hauptaussage gruppiert sich nach der laufenden Summe (die bei jeder Änderung erhöht wird) und berechnet die von Ihnen benötigten Werte.

+0

Ausgezeichnete Lösung! –