2016-07-13 21 views
0

Ich habe Wiederholungs Zeilen in einer Tabelle mit mehreren Terminen:SQL reduziert dates „starten - Ende“ reichen

ID  STATE  DATE 
---------------------------- 
id01 connected 2015-04-04 
id01 connected 2015-04-05 
id01 connected 2015-04-08 
id01 disconect 2015-04-11 
id01 disconect 2015-04-12 
id01 connected 2015-04-13 

ich eine Abfrage mit „Startdatum“ und „Enddatum“, mit diesem Ergebnis will:

ID  STATE START DATE END DATE 
---------------------------------------- 
id01 connected 2015-04-04 2015-04-10 
id01 disconect 2015-04-11 2015-04-12 
id01 connected 2015-04-13 XXXXXXXXXX 

Das letzte „Enddatum“ es ist nicht wichtig (letzter Wert, null, jetzt() ...)

Das wichtigste ist, Änderungsdatum erfassen (in diesem Beispiel keine Zeile für 2015- 04-10, und der gleiche Zustand passierte in 2015-04-13).

Mögliche Lösung? (Nicht gültig)

SELECT ID, STATE, MIN(date), MAX(date) 
    FROM TABLE 
    GROUP BY ID, STATE; 

ist ungültig, da Intervalle fusionieren:

ID  STATE START DATE END DATE 
---------------------------------------- 
id01 connected 2015-04-04 XXXXXXXXXX 
id01 disconect 2015-04-11 2015-04-12 

Abfrage in Impala laufen hat (ähnlich SQL92)

Antwort

1

Impala unterstützt Fensterfunktionen. Dieses Problem ist ein „gap-and-Inseln“ Problem, so kann es mit einer Differenz von Zeilennummern gelöst werden:

für die Differenz
select id, state, min(date) as start_date, max(date) as end_date 
from (select t.*, 
      row_number() over (partition by id order by date) as seqnum_id, 
      row_number() over (partition by id, state order by date) as seqnum_isd 
     from table t 
    ) t 
group by id, state, (seqnum_id - seqnum_isd); 

Die Logik ist nicht schwierig, aber schwierig, wenn man es erst lernen. Es hilft, die Unterabfrage auszuführen und zu sehen, was die Zeilennummernwerte sind - und warum die Differenz jede Gruppe definiert.

+0

Erstaunlich ... einfach und elegant ... ein Problem für mich: das erste Ergebnis , das Enddatum mit Ihrer Anfrage ist 2015-04-08, nicht 2015-04-10. Allerdings eine sehr gute Lösung, Thx – Kzas

+0

Lösung in der Frage veröffentlichen. Danke Gordon – Kzas

0

(Veröffentlicht im Namen des OP).

Von Gordon Linoff's answer, "gap-and-Inseln" Problem meiner Studie Fall zu übersetzen, gibt es die Lösung:

select 
    id, 
    state, 
    start_date, 
    date_add(lag(start_date, 1) over (partition by id order by start_date desc), -1) as end_date 
from 
    (select id, state, min(date) as start_date, max(date) as end_date 
     from (select t.*, 
       row_number() over (partition by id order by date) as seqnum_id, 
       row_number() over (partition by id, state order by date) as seqnum_isd 
      from test t 
     ) t 
    group by id, state, (seqnum_id - seqnum_isd)) t_range 
order by start_date;