Pytanie jest stare, ale to rozwiązanie jest prostsze i szybsze niż to, co zostało opublikowane do tej pory:
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?
Jeśli dodasz ORDER BY
do definicji ramy okna, każdy następny wiersz z większym ORDER BY
wyrażenie ma późniejszy początek ramki. Ani min()
ani first_value()
może wtedy zwrócić „pierwszy” znacznik czasu dla całej partycji. Bez ORDER BY
wszystkie wiersze tej samej partycji są równorzędnymi i uzyskasz pożądany rezultat.
Dodany ORDER BY
działa (nie ten z definicji ramy okiennej, tylko zewnętrzną), ale wydaje się nie mieć sensu i sprawia, że zapytanie jest droższe. Powinieneś prawdopodobnie użyć ORDER BY
klauzula, która jest zgodna z definicją ramy okiennej, aby uniknąć dodatkowych kosztów sortowania:
...
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp;
Nie widzę potrzeby DISTINCT
w tym zapytaniu. Możesz go po prostu dodać, jeśli naprawdę tego potrzebujesz. Lub DISTINCT ON ()
. Ale potem ORDER BY
klauzula staje się jeszcze bardziej istotna. Zobacz:
Jeśli potrzebujesz innych kolumn z tego samego wiersza (nadal sortując według sygnatur czasowych), Twój pomysł za pomocą FIRST_VALUE()
i LAST_VALUE()
może być drogą do zrobienia. Prawdopodobnie musiałbyś dołączyć to do definicji ramy okna wtedy :
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Zobacz: