PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como agrupar as seguintes linhas por valor não exclusivo


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) :sem ORDER 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 um ORDER BY diferente na subconsulta sub usando DISTINCT 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 ).