Wenn Ihr Fall so einfach ist, wie die Beispielwerte vermuten lassen, Antwort von @Giorgos dient gut.
Dies ist jedoch normalerweise nicht der Fall . Wenn die id
Spalte ist eine serial
, können Sie sich nicht darauf verlassen, dass eine Zeile mit einer früheren time
hat auch eine kleinere id
.
Außerdem time
Werte (oder timestamp
wie Sie wahrscheinlich haben) können leicht Duplikate sein, Sie müssen die Sortierreihenfolge eindeutig machen.
Angenommen, beides kann passieren, und Sie möchten die id
ab der Zeile mit der frühesten time
pro Zeitscheibe (eigentlich die kleinste id
zum frühesten Zeitpunkt , es könnte Unentschieden geben), würde diese Abfrage die Situation richtig behandeln:
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
eindeutig sein. Angenommen, Zeit ist nicht unique, fügen Sie die (angenommene eindeutige)id
hinzu um willkürliche Ergebnisse zu vermeiden - die sich zwischen Abfragen auf hinterhältige Weise ändern könnten. -
max(time) OVER (PARTITION BY way, grp)
:ohneORDER BY
, der Fensterrahmen erstreckt sich über alle Zeilen der PARTITION, sodass wir das absolute Maximum pro Zeitscheibe erhalten. -
Die äußere Abfrageschicht ist nur notwendig, um die gewünschte Sortierreihenfolge im Ergebnis zu erzeugen, da wir an einen anderen
ORDER BY
gebunden sind in der Unterabfragesub
durch Verwendung vonDISTINCT ON
. Einzelheiten:
SQL-Fiddle Demonstrieren des Anwendungsfalls.
Wenn Sie die Leistung optimieren möchten, könnte eine plpgsql-Funktion in einem solchen Fall schneller sein. Eng verwandte Antwort:
Übrigens:Verwenden Sie nicht den grundlegenden Typnamen time
als Bezeichner (auch ein reserviertes Wort in Standard-SQL ).