2016-04-20 8 views
1

Ich habe eine Datenbank für alle Temperaturen der letzten 10 Jahre. Jetzt möchte ich alle Perioden finden, in denen die Temperatur über ex lag. 15 Grad.SQL Query verbrachte Zeit zwischen bestimmten Wert

Simplified example: 
... 
2015-05-10 12 
2015-05-11 15 | 
2015-05-12 16 | 
2015-05-13 17 | 
2015-05-14 16 | 
2015-05-15 15 | 
2015-05-16 12 
2015-05-17 11 
2015-05-18 15 | 
2015-05-19 12 
2015-05-20 18 | 
... 

Så jetzt möchte ich alle Zeiten wie diese:

Min   Max 
2015-05-11 2015-05-15 
2015-05-18 2015-05-18 
2015-05-20 2015-05-20 

Jeder Vorschlag, wie diese Abfrage aussehen wird?

+1

sieht aus wie eine Variante der Lücken und Inseln Problem. Sie möchten Zeilen mit einem Wert über 15 finden und die anderen Zeilen wie Lücken behandeln. –

Antwort

1

könnten Sie CTE verwenden

CREATE TABLE #Date (DateT datetime, Value int) 

INSERT INTO #Date 
VALUES ('2015-05-10',12), 
     ('2015-05-11',15), 
     ('2015-05-12',16), 
     ('2015-05-13',17), 
     ('2015-05-14',16), 
     ('2015-05-15',15), 
     ('2015-05-16',12), 
     ('2015-05-17',11), 
     ('2015-05-18',15), 
     ('2015-05-19',12), 
     ('2015-05-20',18) 



WITH t AS (
      SELECT DateT d,ROW_NUMBER() OVER(ORDER BY DateT) i 
      FROM #Date 
      WHERE Value >= 15 
      GROUP BY DateT 
     ) 


SELECT MIN(d) as DataStart,MAX(d) as DataFinal, ROW_NUMBER() OVER(ORDER BY DATEDIFF(day,i,d)) as RN 
FROM t 
GROUP BY DATEDIFF(day,i,d) 

RN Spalte ist optional Sie

SELECT MIN(d) as DataStart,MAX(d) as DataFinal 
FROM t 
GROUP BY DATEDIFF(day,i,d) 
0

Hier ist eine Lösung mit einem Lücken und Inseln Algorithmus verwenden könnten. Es sieht etwas sperrig aus, aber es läuft schnell und skaliert großartig. Es ist auch modular, wenn Sie einen lücke-erlaubten Parameter hinzufügen möchten, und Sie können es in andere Spalten umschreiben und es funktioniert immer noch gut.

Inspiriert von Peter Larssons Beitrag hier: http://www.sqltopia.com/?page_id=83

WITH [theSource](Col1,Col2) 
AS 
(
SELECT Col1,Col2 FROM (VALUES 
('2015-05-10',12), 
('2015-05-11',15), 
('2015-05-12',16), 
('2015-05-13',17), 
('2015-05-14',16), 
('2015-05-15',15), 
('2015-05-16',12), 
('2015-05-17',11), 
('2015-05-18',15), 
('2015-05-19',12), 
('2015-05-20',18) 
) as x(Col1,Col2) 
) 
,filteredSource([Value]) 
AS 
(
SELECT Col1 as [Value] 
FROM theSource WHERE Col2 >= 15 
) 
,cteSource(RangeStart, RangeEnd) 
AS (
    SELECT RangeStart, 
     CASE WHEN [RangeStart] = [RangeEnd] THEN [RangeEnd] ELSE LEAD([RangeEnd]) OVER (ORDER BY Value) END AS [RangeEnd] 
     FROM (
      SELECT [Value], 
       CASE 
        WHEN DATEADD(DAY,1,LAG([Value]) OVER (ORDER BY [Value])) >= [Value] THEN NULL 
        ELSE [Value] 
       END AS RangeStart, 
       CASE 
        WHEN DATEADD(DAY,-1,LEAD([Value]) OVER (ORDER BY [Value])) <= [Value] THEN NULL 
        ELSE [Value] 
           END AS RangeEnd 
         FROM filteredSource 
       ) AS d 
    WHERE RangeStart IS NOT NULL 
     OR RangeEnd IS NOT NULL 
) 


SELECT RangeStart AS [Min], 
    RangeEnd AS [Max] 
FROM cteSource 
WHERE RangeStart IS NOT NULL; 
+0

Was ist, wenn Sie eine Lücke in Tagen haben? Sagen Sie, wenn Sie Daten für einige Tage während 10 Jahren fehlen – Geir

+0

Das ist in Ordnung. Dies zeigt nur Inseln. –