Om ditt fall är så enkelt som exempelvärdena antyder, @Giorgos svar tjänar fint.
Men det är vanligtvis inte fallet . Om id
kolumnen är en serial
, kan du inte lita på antagandet att en rad med en tidigare time
har också ett mindre id
.
Också time
värden (eller timestamp
som du förmodligen har) lätt kan vara dubbletter, du måste göra sorteringsordningen entydig.
Förutsatt att båda kan hända och att du vill ha id
från raden med den tidigaste time
per tidssegment (faktiskt den minsta id
för den tidigaste tiden , det kan finnas kopplingar), skulle denna fråga hantera situationen korrekt:
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
att vara entydig. Förutsatt att tiden inte är unikt, lägg till (antaget unikt)id
för att undvika godtyckliga resultat - som kan ändras mellan frågor på lömska sätt. -
max(time) OVER (PARTITION BY way, grp)
:utanORDER BY
, spänner fönsterramen över alla rader i PARTITIONEN, så vi får det absoluta maxvärdet per tidssegment. -
Det yttre frågeskiktet är bara nödvändigt för att producera önskad sorteringsordning i resultatet, eftersom vi är bundna till en annan
ORDER BY
i underfrågansub
genom att användaDISTINCT ON
. Detaljer:
SQL Fiddle demonstrerar användningsfallet.
Om du vill optimera prestanda kan en plpgsql-funktion vara snabbare i ett sådant fall. Närbesläktat svar:
Bortsett från:använd inte det grundläggande typnamnet time
som identifierare (även ett reserverat ord i standard SQL ).