Si su caso es tan simple como sugieren los valores de ejemplo, respuesta de @Giorgos sirve muy bien.
Sin embargo, ese normalmente no es el caso . Si el id
la columna es un serial
, no puede confiar en la suposición de que una fila con una time
anterior también tiene un id
más pequeño .
También, time
valores (o timestamp
como probablemente lo haya hecho) pueden duplicarse fácilmente, debe hacer que el orden de clasificación no sea ambiguo.
Asumiendo que ambos pueden suceder, y desea el id
desde la fila con la time
más antigua por segmento de tiempo (en realidad, el más pequeño id
por el tiempo más temprano , podría haber empates), esta consulta trataría la situación correctamente:
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. Asumiendo que el tiempo no único, agregue el (supuesto único)id
para evitar resultados arbitrarios, que podrían cambiar entre consultas de manera furtiva. -
max(time) OVER (PARTITION BY way, grp)
:sinORDER BY
, el marco de la ventana abarca todas las filas de la PARTICIÓN, por lo que obtenemos el máximo absoluto por intervalo de tiempo. -
La capa de consulta externa solo es necesaria para producir el orden de clasificación deseado en el resultado, ya que estamos vinculados a un
ORDER BY
diferente en la subconsultasub
usandoDISTINCT ON
. Detalles:
SQL Fiddle demostrando el caso de uso.
Si busca optimizar el rendimiento, una función plpgsql podría ser más rápida en tal caso. Respuesta estrechamente relacionada:
Aparte:no use el nombre de tipo básico time
como identificador (también una palabra reservada en SQL estándar ).