PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Erster und letzter Wert der Fensterfunktion in einer Zeile in PostgreSQL

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: