Hvis din sag er så enkel, som eksempelværdierne antyder, @Giorgos' svar tjener pænt.
Det er dog typisk ikke tilfældet . Hvis id
kolonne er en serial
, kan du ikke stole på den antagelse, at en række med et tidligere time
har også et mindre id
.
Også time
værdier (eller timestamp
som du sikkert har) nemt kan være dubletter, skal du gøre sorteringsrækkefølgen utvetydig.
Forudsat at begge dele kan ske, og du vil have id
fra rækken med det tidligste time
pr. tidsudsnit (faktisk den mindste id
for det tidligste tidspunkt , der kunne være bånd), ville denne forespørgsel håndtere 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
at være entydig. Forudsat at tiden ikke er unikt, tilføj (antaget unikt)id
for at undgå vilkårlige resultater - det kan ændre sig mellem forespørgsler på luskede måder. -
max(time) OVER (PARTITION BY way, grp)
:udenORDER BY
, spænder vinduesrammen over alle rækker i PARTITIONEN, så vi får det absolutte maksimum pr. tidsudsnit. -
Det ydre forespørgselslag er kun nødvendigt for at producere den ønskede sorteringsrækkefølge i resultatet, da vi er bundet til en anden
ORDER BY
i underforespørgslensub
ved at brugeDISTINCT ON
. Detaljer:
SQL Fiddle demonstrerer brugssagen.
Hvis du ønsker at optimere ydeevnen, kan en plpgsql-funktion være hurtigere i et sådant tilfælde. Nært beslægtet svar:
Til side:Brug ikke det grundlæggende typenavn time
som identifikator (også et reserveret ord i standard SQL ).