Als uw zaak zo eenvoudig is als de voorbeeldwaarden suggereren, @Giorgos' antwoord serveert mooi.
Dat is echter meestal niet het geval . Als de id
kolom is een serial
, kunt u er niet van uitgaan dat een rij met een eerdere time
heeft ook een kleinere id
.
Ook time
waarden (of timestamp
zoals je waarschijnlijk hebt) kunnen gemakkelijk duplicaten zijn, je moet de sorteervolgorde ondubbelzinnig maken.
Ervan uitgaande dat beide kunnen gebeuren, en u wilt de id
uit de rij met de vroegste time
per tijdschijf (eigenlijk de kleinste id
voor de vroegste tijd , er kunnen verbanden zijn), zou deze vraag de situatie goed behandelen:
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
eenduidig te zijn. Ervan uitgaande dat de tijd niet . is uniek, voeg de (veronderstelde unieke)id
. toe om willekeurige resultaten te vermijden - die op stiekeme manieren tussen zoekopdrachten kunnen veranderen. -
max(time) OVER (PARTITION BY way, grp)
:zonderORDER BY
, het raamkozijn omspant alle rijen van de PARTITION, dus we krijgen het absolute maximum per tijdsegment. -
De buitenste querylaag is alleen nodig om de gewenste sorteervolgorde in het resultaat te produceren, aangezien we gebonden zijn aan een andere
ORDER BY
in de subquerysub
doorDISTINCT ON
. te gebruiken . Details:
SQL Fiddle de use case demonstreren.
Als u de prestaties wilt optimaliseren, kan een plpgsql-functie in zo'n geval sneller zijn. Nauw verwant antwoord:
Terzijde:gebruik niet de basistypenaam time
als identifier (ook een gereserveerd woord in standaard SQL ).