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, idessere 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 BYnella sottoquerysubutilizzandoDISTINCT 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 ).