CREATEOR REPLACE VIEW daily_trans ASSELECTDISTINCT
trans_date, first_value(trans_time)OVER w AS first_time, first_value(id)OVER w AS first_id, last_value(trans_time)OVER w AS last_time, last_value(id)OVER w AS last_id, calculate_status(min(trans_time)OVER w, max(trans_time)OVER w)AS status FROM trans
WINDOW w AS(PARTITIONBY trans_date ORDERBY trans_time, idROWSBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)ORDERBY1;
Ich habe idals sekundäre ORDERSpalte in die Fensterklausel eingefügt , um die Sortierreihenfolge bei identischen Zeiten pro Tag stabil zu machen.
Wenn Sie mit Fensterfunktionen nicht vertraut sind, lesen Sie unbedingt dieses Kapitel des Handbuchs .
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGist eine nicht so häufig verwendete Klausel zum Anpassen des Fensterrahmens, da last_value()immer der letzte Wert der gesamten Partition (das Datum) und nicht der letzte Wert bis zum aktuellen Wert (einschließlich Peers) gemäß der Sortierreihenfolge zurückgegeben werden soll.
Vielen Dank @Erwin Brandstetter, es ist eine ausgezeichnete Antwort.
Zufälliger Joe
4
Sie wollen ungefähr so etwas
select min_trans_time, min_trans.id as min_trans_time_id,
max_trans_time, max_trans.id as max_trans_time_idfrom(select trans_date,
max(trans_time)as max_trans_time,
min(trans_time)as min_trans_time,from trans groupby trans_date) min_max_trans,
trans as min_trans,
trans as max_transwhere min_trans.trans_time = min_max_trans.min_trans_timeand max_trans.trans_time = min_max_trans.max_trans_time
Was möglicherweise nicht stabil ist, wenn mehrere transes dasselbe teilen trans_time( dh, wenn die Abfrage für denselben Datensatz ausgeführt wird, kann dies zu unterschiedlichen Ergebnissen führen. Eine einfache Möglichkeit, dies zu lösen, besteht darin, die maximale oder minimale ID auszuwählen. Zum Beispiel könnte dies natürlich die Ergebnisse beeinflussen :).
Sie können auch Fensterfunktionen verwenden, wenn Sie PostgreSQL 8.4 oder höher verwenden. Sie bieten eine klarere Abfrage (klar, wenn Sie mit Fensterfunktionen vertraut sind :), und sie ermöglichen es Ihnen, Dinge zu tun, die mit der obigen Strategie ziemlich schwierig zu tun sind (z. B. den 2. höheren Wert anstelle des Maximums zu erhalten). Nach meiner kurzen Erfahrung schnitten sie jedoch schlechter ab als der hier vorgeschlagene Self-Join-Ansatz. Erwins Antwort enthält eine Version der Abfrage mit Fensterfunktionen. Es wäre interessant festzustellen, welche Abfrage besser ausgeführt wird und / oder besser optimiert werden kann (durch Hinzufügen von Indizes usw.).
+1 für die Berücksichtigung nicht eindeutiger Zeiten pro Tag (obwohl Sie das nicht gelöst haben) und die Erwähnung von Fensterfunktionen (obwohl Sie sie nicht verwendet haben).
Erwin Brandstetter
Ich habe deine positiv bewertet. Ich schlage diese Lösung vor und behalte sie hier, da Fensterfunktionen nicht in allen RDBMS verfügbar oder standardisiert sind und möglicherweise weniger leistungsfähig sind. Allerdings werde ich meine Antwort ein wenig bearbeiten ...
Alex
2
Tatsächlich sind Fensterfunktionen im SQL: 2003-Standard enthalten und werden von allen wichtigen RDBMS (Oracle, PostgreSQL, SQL Server, ...) unterstützt. Die einzige bemerkenswerte Ausnahme ist MySQL. Andererseits unterstützt MySQL nicht einmal CTEs (ein weiterer wichtiger SQL-Standard).
Erwin Brandstetter
Sind sie? Ich dachte, jedes RDBMS verwendet eine andere Syntax. Wenn ja, verwirrt es mich, dass Limit / Offset nicht standardisiert ist (was nicht das letzte Mal war, als ich IIRC überprüft habe - obwohl das schon lange her ist).
Alex
2
RDBMS verwenden für fast jedes Detail eine etwas andere Syntax. Das standardkonformste RDBMS ist wahrscheinlich PostgreSQL. Das ändert nichts an der Tatsache, dass SQL-Standards existieren und dass die Hauptakteure sie größtenteils implementieren.
Sie wollen ungefähr so etwas
Was möglicherweise nicht stabil ist, wenn mehrere
trans
es dasselbe teilentrans_time
( dh, wenn die Abfrage für denselben Datensatz ausgeführt wird, kann dies zu unterschiedlichen Ergebnissen führen. Eine einfache Möglichkeit, dies zu lösen, besteht darin, die maximale oder minimale ID auszuwählen. Zum Beispiel könnte dies natürlich die Ergebnisse beeinflussen :).Sie können auch Fensterfunktionen verwenden, wenn Sie PostgreSQL 8.4 oder höher verwenden. Sie bieten eine klarere Abfrage (klar, wenn Sie mit Fensterfunktionen vertraut sind :), und sie ermöglichen es Ihnen, Dinge zu tun, die mit der obigen Strategie ziemlich schwierig zu tun sind (z. B. den 2. höheren Wert anstelle des Maximums zu erhalten). Nach meiner kurzen Erfahrung schnitten sie jedoch schlechter ab als der hier vorgeschlagene Self-Join-Ansatz. Erwins Antwort enthält eine Version der Abfrage mit Fensterfunktionen. Es wäre interessant festzustellen, welche Abfrage besser ausgeführt wird und / oder besser optimiert werden kann (durch Hinzufügen von Indizes usw.).
quelle