Se il tuo caso è semplice come suggeriscono i valori di esempio, Risposta di @Giorgos serve bene.
Tuttavia, solitamente non è così . Se l'id
colonna è un serial
, non puoi fare affidamento sul presupposto che una riga con un time
precedente ha anche un id
più piccolo .
Inoltre, time
valori (o timestamp
come probabilmente hai fatto) possono essere facilmente duplicati, è necessario rendere l'ordinamento univoco.
Supponendo che entrambi possano accadere e tu voglia l'id
dalla riga con la prima time
per intervallo di tempo (in realtà, il più piccolo id
per la prima volta , potrebbero esserci dei legami), questa query tratterebbe la situazione in modo appropriato:
SELECT *
FROM (
SELECT DISTINCT ON (way, grp)
id, way, time AS time_from
, max(time) OVER (PARTITION BY way, grp) AS time_to
FROM (
SELECT *
, row_number() OVER (ORDER BY time, id) -- id as tie breaker
- row_number() OVER (PARTITION BY way ORDER BY time, id) AS grp
FROM table1
) t
ORDER BY way, grp, time, id
) sub
ORDER BY time_from, id;
-
ORDER BY time, id
essere inequivocabile. Supponendo che il tempo non sia unico, aggiungi l'id
(presunto univoco). per evitare risultati arbitrari, che potrebbero cambiare tra le query in modi subdoli. -
max(time) OVER (PARTITION BY way, grp)
:senzaORDER BY
, il frame della finestra si estende su tutte le righe della PARTITION, quindi otteniamo il massimo assoluto per intervallo di tempo. -
Il livello di query esterno è necessario solo per produrre l'ordinamento desiderato nel risultato, poiché siamo vincolati a un diverso
ORDER BY
nella sottoquerysub
utilizzandoDISTINCT ON
. Dettagli:
SQL Fiddle dimostrando il caso d'uso.
Se stai cercando di ottimizzare le prestazioni, una funzione plpgsql potrebbe essere più veloce in questo caso. Risposta strettamente correlata:
A parte:non utilizzare il nome del tipo di base time
come identificatore (anche una parola riservata in SQL standard ).