Jeśli Twoja sprawa jest tak prosta, jak sugerują wartości przykładu, odpowiedź @Giorgos służy ładnie.
Jednak zazwyczaj tak nie jest . Jeśli id
kolumna jest serial
, nie można polegać na założeniu, że wiersz z wcześniejszym time
ma również mniejszy id
.
Ponadto time
wartości (lub timestamp
tak jak prawdopodobnie masz) mogą łatwo być duplikatami, musisz uczynić porządek sortowania jednoznacznym.
Zakładając, że jedno i drugie może się zdarzyć i potrzebujesz id
z wiersza z najwcześniejszym time
na wycinek czasu (w rzeczywistości najmniejszy id
najwcześniej czas , mogą być remisy), to zapytanie rozwiązałoby sytuację prawidłowo:
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
być jednoznacznym. Zakładając, że czas nie unikalny, dodaj (zakładany unikalny)id
aby uniknąć arbitralnych wyników - które mogą zmieniać się między zapytaniami w podstępny sposób. -
max(time) OVER (PARTITION BY way, grp)
:bezORDER BY
, rama okna obejmuje wszystkie wiersze PARTYCJI, więc otrzymujemy absolutne maksimum na wycinek czasu. -
Zewnętrzna warstwa zapytania jest konieczna tylko do uzyskania pożądanej kolejności sortowania w wyniku, ponieważ jesteśmy związani z innym
ORDER BY
w podzapytaniusub
za pomocąDISTINCT ON
. Szczegóły:
Skrzypce SQL zademonstrowanie przypadku użycia.
Jeśli chcesz zoptymalizować wydajność, funkcja plpgsql może być w takim przypadku szybsza. Ściśle powiązana odpowiedź:
Poza tym:nie używaj podstawowej nazwy typu time
jako identyfikator (również zastrzeżone słowo w standardowym SQL ).