Kombinieren Zeilen, wenn die Endzeit der einen ist die Startzeit eines anderen (Oracle)
Ich kann einfach nicht scheinen, um diese Abfrage herausgefunden. Ich brauche kombinieren, um Reihen von Zeit-aufeinander folgende Staaten in einer einzigen Staates.
Diese Frage ist ähnlich der Frage gefunden, außer hier arbeite ich mit Oracle 10 nicht-SQL Server: Kombinieren Zeilen, wenn die Endzeit der einen ist die Startzeit eines anderen
Beispiel Daten:
name start_inst end_inst code subcode
Person1 9/12/2011 10:55 9/12/2011 11:49 161 50
Person1 9/12/2011 11:49 9/12/2011 11:55 107 28
Person1 9/12/2011 11:55 9/12/2011 12:07 161 50
Person1 9/12/2011 12:07 9/12/2011 12:26 161 50
Person1 9/12/2011 12:26 9/12/2011 12:57 161 71
Person1 9/12/2011 12:57 9/12/2011 13:07 161 71
Person1 9/12/2011 13:07 9/12/2011 13:20 52 50
Und ich möchte die folgende Ausgabe erhalten:
name start_inst end_inst code subcode
Person1 9/12/2011 10:55 9/12/2011 11:49 161 50
Person1 9/12/2011 11:49 9/12/2011 11:55 107 28
Person1 9/12/2011 11:55 9/12/2011 12:26 161 50
Person1 9/12/2011 12:26 9/12/2011 13:07 161 71
Person1 9/12/2011 13:07 9/12/2011 13:20 52 50
Hier ist Beispiel SQL:
CREATE TABLE Data (
name varchar2(132 BYTE) not null,
start_inst DATE not null,
end_inst DATE not null,
code number(3) not null,
subcode number(3) not null
);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 10:55','9/12/2011 11:49',161, 50);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 11:49','9/12/2011 11:55',107,28);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 11:55','9/12/2011 12:07',161,50);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 12:07','9/12/2011 12:26',161,50);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 12:26','9/12/2011 12:57',161,71);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 12:57','9/12/2011 13:07',161,71);
INSERT INTO Data(name,start_inst,end_inst, code, code2) VALUES('Person1','9/12/2011 13:07','9/12/2011 13:20',52,50);
Vielen Dank im Voraus!
- Um Ihr Beispiel SQL korrekt ausgeführt wird, möglicherweise die folgenden änderungen vornehmen: a) fügen Sie
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH24:MI';
vor dem INSERT-Anweisungen, so dass die Datums-Zeichenketten korrekt interpretiert werden (oder explizit TO_DATE mit diesem format in die INSERT-Anweisungen), und b) ändern Sie die INSERT-Anweisungen zu verwenden "subcode" statt "code2", so dass Sie Stimme mit der CREATE TABLE-Anweisung. - Pflege zu wählen und akzeptieren Sie die Antwort, die Ihnen geholfen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vielleicht? (Ich habe keinen SQL-Maschine, um es zu laufen)
Hier ist eine Lösung mit einer rekursiven Abfrage anstelle der analytischen Funktionen (wie vorgeschlagen von @wildplasser):
Den
connect by
- Klausel in der inneren Abfrage werden die Daten zurückgegeben werden, die in einer hierarchischen Weise.connect_by_root
gibt uns den Wert an der Wurzel jeder Verzweigung. Denn wir haben nicht ein guter Kandidat für einestart with
Klausel, wir werden alle untergeordneten Zeilen (woend_inst
gleich eine weitere Zeilestart_inst
und alle anderen Spalten sind die gleichen) mehrfach: einmal als root und einmal (oder mehr) wie ein Zweig. Unter dermin
von der Wurzel beseitigt diese extra Zeilen, während er uns einen Wert für eine Gruppe auf, die in der äußeren Abfrage.In der äußeren Abfrage, führen wir ein weiteres
group by
zu konsolidieren, die Reihen. Der Unterschied ist, dass, in diesem Fall, wir habenroot_start
es auch zu identifizieren, welche Zeilen aufeinanderfolgend sind und daher konsolidiert werden müssen.Hier ist ein anderer Ansatz:
Grundsätzlich:
Für jede Zeile Eine Unterabfrage findet die frühere Endzeit für die der gegebene name, code und subcode.
Für jede Zeile eine Unterabfrage B berechnet die "Gruppe Anzahl" -- eine laufende Zählung der vorhergehenden Zeilen (in der Reihenfolge der start_inst, name, code und subcode), wo die früheren Ende der Zeit berechnet, die in Schritt 1 ist nicht gleich der start-Zeit.
Der äußeren Abfrage Aggregate von Gruppe Anzahl.
Für besser oder schlechter, ist dieser Ansatz, im Gegensatz zu @stevo ist, wird eine neue "Gruppe", wenn es eine "Lücke" zwischen der Endzeit der einen Aufnahme und die Anfangszeit der nächsten. Zum Beispiel, wenn Sie waren, um eine Lücke zu schaffen zwischen 12:57 und 13:00 Uhr so...
...die obige Abfrage würde return zwei Zeilen wie diese...
...in der Erwägung, dass @stevo ' s query zurückgeben würde eine Zeile wie diese...
Hoffe, das hilft.
ORDER BY start_inst, name, code, subcode
in der ZÄHLUNG, es sollte sagenORDER BY name, code, subcode, start_inst
, so imitiert, wird die Reihenfolge durch die LAG unten. Mit den Beispiel-Daten (modifiziert durch @brianc oben) gibt es keinen Unterschied in den Ergebnissen, sondern mit den real-Daten ich für mein problem diese änderung wurde notwendig, um die richtigen Ergebnisse. Danke!!!ORDER BY
imCOUNT
beabsichtigt war, so dass wir (auch) es nutzen kann, um die gewünschte Reihenfolge der endgültigen Ergebnisse in der original-poster der Frage. Vielleicht ist das problem, das Sie konfrontiert sind, ist etwas anders? Zu imitieren, dieLAG
, man könnte hinzufügen, einPARTITION BY
zu denCOUNT
und bewegen Sie denname, code, subcode
um es aus seinerORDER BY
. Sie müssen möglicherweise ändern Sie denORDER BY
in der äußeren Abfrage, obwohl...INSERT INTO Data VALUES('Person1','9/12/2011 12:00','9/12/2011 12:01',99,99)
, wodurch diese situation in den OP-Daten, werden Sie sehen, dass 161-50 Zeilen beginnend um 11:55 und 12:07 nicht mehr in derselben Gruppe, obwohl Sie aufeinander, sondern meine änderung, um Ihren code legen Sie Sie wieder in der gleichen Gruppe. Also du hast Recht, es gibt keine Fehler in deinem code, nur unterschiedliche Daten. Danke für die Lösung & für die Zeit nehmen für meine Anliegen.Anpassung desm s-Abfrage, ich denke, das sollte funktionieren
Kannst du das mit einer rekursiven query (irgendwas mit VERBINDUNG VON /VOR in oracle, IIRC) habe ich die gleiche Sache für Postgres in diesem thread : Holen Sie total time Intervall von mehreren Zeilen, wenn die Sequenz nicht gebrochen
Müssen Sie möglicherweise ein bisschen Nacharbeiten, damit es passt in die oracle-syntax.