2017-02-16 8 views
-1

Hallo ich unten in täglich eine Daten haben:Gruppierung nach Datumsbereich auf Wert basiert

daytime  value 
01.01.2017  20000 
02.01.2017  20000 
03.01.2017  20000 
04.01.2017  35000 
05.01.2017  35000 
06.01.2017  40000 
07.01.2017  40000 
08.01.2017  50000 

Wie kann ich so in Datumsbereich Format haben, wie unten?

FromDate  ToDate  Value 
01.01.2017 03.01.2017 20000 
04.01.2017 05.01.2017 35000 
06.01.2017 07.01.2017 40000 
08.01.2017 08.01.2017 50000 

Vielen Dank!

Antwort

3

Tabibitosan diese Griffe sehr leicht:

WITH your_table AS (SELECT to_date('01/01/2017', 'dd/mm/yyyy') daytime, 20000 VALUE FROM dual UNION ALL 
        SELECT to_date('02/01/2017', 'dd/mm/yyyy') daytime, 20000 VALUE FROM dual UNION ALL 
        SELECT to_date('03/01/2017', 'dd/mm/yyyy') daytime, 20000 VALUE FROM dual UNION ALL 
        SELECT to_date('04/01/2017', 'dd/mm/yyyy') daytime, 35000 VALUE FROM dual UNION ALL 
        SELECT to_date('05/01/2017', 'dd/mm/yyyy') daytime, 35000 VALUE FROM dual UNION ALL 
        SELECT to_date('06/01/2017', 'dd/mm/yyyy') daytime, 40000 VALUE FROM dual UNION ALL 
        SELECT to_date('07/01/2017', 'dd/mm/yyyy') daytime, 40000 VALUE FROM dual UNION ALL 
        SELECT to_date('08/01/2017', 'dd/mm/yyyy') daytime, 50000 VALUE FROM dual UNION ALL 
        SELECT to_date('09/01/2017', 'dd/mm/yyyy') daytime, 20000 VALUE FROM dual) 
-- end of mimicking your table with data in it. See SQL below: 
SELECT MIN(daytime) fromdate, 
     MAX(daytime) todate, 
     VALUE 
FROM (SELECT daytime, 
       VALUE, 
       row_number() OVER (ORDER BY daytime) - row_number() OVER (PARTITION BY VALUE ORDER BY daytime) grp 
     FROM your_table) 
GROUP BY grp, 
     VALUE 
ORDER BY MIN(daytime); 

FROMDATE TODATE   VALUE 
---------- ---------- ---------- 
01/01/2017 03/01/2017  20000 
04/01/2017 05/01/2017  35000 
06/01/2017 07/01/2017  40000 
08/01/2017 08/01/2017  50000 
09/01/2017 09/01/2017  20000 

Was das bedeutet ist die Zeilennummer für alle nach Datum geordnet Reihen vergleichen und dann die Zeilennummer für alle Zeilen für jeden nach Datum sortierten Wert. Wenn die Wertezeilen im Hauptdatensatz fortlaufend sind, bleibt der Unterschied zwischen den beiden Datensätzen derselbe, so dass Sie anschließend eine Gruppierung vornehmen können. Wenn es eine Lücke gibt, dann erhöht sich der Unterschied.

In Ihrem Beispiel oben sind die ersten drei Zeilen für Wert = 20000 die ersten drei Zeilen des gesamten Satzes, also ist die Differenz 0. Der vierte Wert = 20000 Zeile ist jedoch die 9. Zeile im Ganzen gesetzt, so dass der Unterschied jetzt 5 ist. Sie können leicht sehen, dass der Wert von 20000 in zwei Gruppen fällt, und als solche können Sie die Min/Max-Tage für jede Gruppe separat finden, indem Sie diese Differenzberechnung in die Gruppenklausel aufnehmen.

N.B. Dies setzt voraus, dass die Daten in Ihren Daten fortlaufend sind oder dass bei fehlenden Daten davon ausgegangen wird, dass der Wert für die fehlenden Daten gleich bleibt. Wenn Tage fehlen und die Werte in einer Lücke in verschiedenen Gruppen angezeigt werden sollen, müssen Sie eine externe Verknüpfung mit einer Unterabfrage erstellen, die die fehlenden Daten enthält. In diesem Fall denke ich, dass die Antwort von GurV (mit der Zusatzklausel in der Fallbeschreibung, die ich in den Kommentaren erwähnt habe) die beste wäre, da dies die Notwendigkeit vermeidet, sich einer Liste aufeinanderfolgender Daten anzuschließen.

+0

Bingo! Es klappt! Vielen Dank :) – akira

+0

Nicht sicher, wie Sie die N.B. - Vielleicht meinst du, wenn oben zehn Zeilen stehen, alle mit dem Wert 20000, aber die Daten sind vier aufeinanderfolgende Tage, dann eine Lücke und dann sechs weitere aufeinanderfolgende Tage, und das sollte zwei statt einer Zeile ergeben ... Wenn das ist was du meinst, dann kann eine kleine Modifikation von ** Tabibitosan ** direkt damit umgehen.Um 'grp' zu erstellen, verwenden Sie' day' selbst anstelle der ersten 'row_number()'; Auf diese Weise werden die 'grp'-Werte als Daten anstelle von Zahlen angezeigt, aber das Ganze funktioniert genauso. – mathguy

+0

Guter Punkt, ta; Ich hätte nie zuvor daran gedacht! Ich werde am Montag damit spielen. * :-) – Boneist

1

Wenn ich richtig verstehe, möchten Sie den Wert nur gruppieren, wenn sie für aufeinanderfolgende Daten übereinstimmen.

Sie können Fensterfunktionen verwenden, um Gruppen basierend auf Wert und zunehmender Datumsreihenfolge zu generieren und dann die erforderlichen Aggregate zu finden.

with your_table(daytime  ,value) as (
    select to_date('13.02.2017','dd.mm.yyyy'),25000 from dual union all 
    select to_date('14.02.2017','dd.mm.yyyy'),20000 from dual union all 
    select to_date('15.01.2017','dd.mm.yyyy'),90000 from dual union all 
    select to_date('16.01.2017','dd.mm.yyyy'),90000 from dual union all 
    select to_date('17.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('18.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('19.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('20.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('21.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('22.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('23.01.2017','dd.mm.yyyy'),95800 from dual union all 
    select to_date('24.01.2017','dd.mm.yyyy'),90000 from dual union all 
    select to_date('25.01.2017','dd.mm.yyyy'),90000 from dual union all 
    select to_date('26.01.2017','dd.mm.yyyy'),90000 from dual 
) 
select 
    min(daytime) fromdate, 
    max(daytime) todate, 
    value 
from (
    select 
     t.*, 
     sum(x) over (order by daytime) grp 
    from (
     select 
      t.*, 
      case when value = lag(value) over (order by daytime) 
      then 0 else 1 end x 
     from your_table t 
    ) t 
) t group by grp, value 
order by fromdate; 

Produziert:

FROMDATE TODATE  VALUE 
15-JAN-17 16-JAN-17 90000 
17-JAN-17 23-JAN-17 95800 
24-JAN-17 26-JAN-17 90000 
13-FEB-17 13-FEB-17 25000 
14-FEB-17 14-FEB-17 20000 
+0

Hallo ich sehe doppelten Wert mit Ihrer Lösung, ich werde Beispiel später zeigen, danke! – akira

+0

@akirax was meinst du, du siehst doppelte Werte mit GurVs Lösung? Es sieht so aus, als ob es für mich funktioniert, wenn ich es mit einigen Testdaten versuche. Es gibt sicherlich die Ausgabe, die Sie in Ihre Antwort für die eingegebenen Daten eingegeben haben. – Boneist

+0

@akirax - Es funktioniert. Bitte sehen Sie das Update – GurV