sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo agrupar las siguientes filas por valor no único

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) :sin ORDER 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 subconsulta sub usando DISTINCT 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 ).