Die Frage ist alt, aber diese Lösung ist einfacher und schneller als das, was bisher gepostet wurde:
SELECT b.machine_id
, batch
, timestamp_sta
, timestamp_stp
, min(timestamp_sta) OVER w AS batch_start
, max(timestamp_stp) OVER w AS batch_end
FROM db_data.sta_stp a
JOIN db_data.ll_lu b ON a.ll_lu_id = b.id
WINDOW w AS (PARTITION BY batch, b.machine_id) -- No ORDER BY !
ORDER BY timestamp_sta, batch, machine_id; -- why this ORDER BY?
Wenn Sie ORDER BY
hinzufügen zur Fensterrahmendefinition, jede nächste Zeile mit einem größeren ORDER BY
Ausdruck hat einen späteren Frame-Start. Weder min()
noch first_value()
kann dann den "ersten" Zeitstempel für die gesamte Partition zurückgeben. Ohne ORDER BY
alle Zeilen derselben Partition sind Peers und Sie erhalten Ihr gewünschtes Ergebnis.
Ihr hinzugefügter ORDER BY
funktioniert (nicht die in der Fensterrahmendefinition, die äußere), scheint aber keinen Sinn zu machen und verteuert die Abfrage. Sie sollten wahrscheinlich einen ORDER BY
verwenden Klausel, die mit Ihrer Fensterrahmendefinition übereinstimmt, um zusätzliche Sortierkosten zu vermeiden:
...
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp;
Ich sehe keine Notwendigkeit für DISTINCT
in dieser Abfrage. Sie können es einfach hinzufügen, wenn Sie es tatsächlich brauchen. Oder DISTINCT ON ()
. Aber dann der ORDER BY
Klausel wird noch relevanter. Siehe:
Wenn Sie einige andere Spalten aus derselben Zeile benötigen (während Sie immer noch nach Zeitstempeln sortieren), Ihre Idee mit FIRST_VALUE()
und LAST_VALUE()
könnte der richtige Weg sein. Sie müssten dies wahrscheinlich dann an die Fensterrahmendefinition anhängen :
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Siehe: