La domanda è vecchia, ma questa soluzione è più semplice e veloce di quella pubblicata finora:
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?
Se aggiungi ORDER BY
alla definizione del telaio della finestra, ogni riga successiva con un ORDER BY
maggiore l'espressione ha un inizio di frame successivo. Né min()
né first_value()
può restituire il "primo" timestamp per l'intera partizione quindi. Senza ORDER BY
tutte le righe della stessa partizione sono peer e ottieni il risultato desiderato.
Il tuo ORDER BY
aggiunto funziona (non quello nella definizione del frame della finestra, quello esterno), ma non sembra avere senso e rende la query più costosa. Probabilmente dovresti usare un ORDER BY
clausola che concorda con la definizione del telaio della finestra per evitare costi di ordinamento aggiuntivi:
...
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp;
Non vedo la necessità di DISTINCT
in questa domanda. Potresti semplicemente aggiungerlo se ne hai davvero bisogno. Oppure DISTINCT ON ()
. Ma poi il ORDER BY
clausola diventa ancora più rilevante. Vedi:
Se hai bisogno di altre colonne della stessa riga (mentre stai ancora ordinando per timestamp), la tua idea con FIRST_VALUE()
e LAST_VALUE()
potrebbe essere la strada da percorrere. Probabilmente dovresti aggiungerlo alla definizione del frame della finestra quindi :
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Vedi: