PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Primo e ultimo valore della funzione finestra in una riga in PostgreSQL

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()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: