Se o seu caso for tão simples quanto os valores de exemplo sugerem, resposta de @Giorgos serve bem.
No entanto, isso normalmente não é o caso . Se o
id
coluna é uma serial
, você não pode confiar na suposição de que uma linha com uma time
anterior também tem um id
menor .Além disso,
time
valores (ou timestamp
como você provavelmente tem) podem ser facilmente duplicados, você precisa tornar a ordem de classificação inequívoca. Assumindo que ambos podem acontecer, e você quer o
id
da linha com a time
mais antiga por fatia de tempo (na verdade, a menor id
pela hora mais cedo , pode haver empates), essa consulta lidaria com a situação corretamente: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
ser inequívoco. Supondo que o tempo não exclusivo, adicione o (supostamente exclusivo)id
para evitar resultados arbitrários - isso pode mudar entre as consultas de maneiras sorrateiras.
-
max(time) OVER (PARTITION BY way, grp)
:semORDER BY
, o quadro da janela abrange todas as linhas da PARTITION, de modo que obtemos o máximo absoluto por fatia de tempo.
-
A camada de consulta externa só é necessária para produzir a ordem de classificação desejada no resultado, pois estamos vinculados a umORDER BY
diferente na subconsultasub
usandoDISTINCT ON
. Detalhes:
SQL Fiddle demonstrando o caso de uso.
Se você deseja otimizar o desempenho, uma função plpgsql pode ser mais rápida nesse caso. Resposta intimamente relacionada:
Além:não use o nome de tipo básico
time
como identificador (também uma palavra reservada no SQL padrão ).