Otázka je stará, ale toto řešení je jednodušší a rychlejší než to, co bylo dosud zveřejněno:
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?
Pokud přidáte ORDER BY
k definici okenního rámu, každý další řádek s větším ORDER BY
výraz má pozdější začátek rámce. Ani min()
ani first_value()
pak může vrátit "první" časové razítko pro celý oddíl. Bez ORDER BY
všechny řádky stejného oddílu jsou rovnocenné a získáte požadovaný výsledek.
Váš přidaný ORDER BY
funguje (ne ten v definici okenního rámu, ten vnější), ale zdá se, že to nedává smysl a prodražuje dotaz. Pravděpodobně byste měli použít ORDER BY
klauzule, která souhlasí s vaší definicí okenního rámu, aby se zabránilo dalším nákladům na třídění:
...
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp;
Nevidím potřebu DISTINCT
v tomto dotazu. Můžete jej přidat, pokud to skutečně potřebujete. Nebo DISTINCT ON ()
. Ale pak ORDER BY
klauzule se stává ještě relevantnější. Viz:
Pokud potřebujete nějaké další sloupce ze stejného řádku (a přitom stále řadit podle časových razítek), váš nápad s FIRST_VALUE()
a LAST_VALUE()
může být cesta. Pravděpodobně to budete muset přidat k definici okenního rámu pak :
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Viz: