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

Cómo agregar un conteo continuo a las filas en una 'racha' de días consecutivos

Sobre la base de esta tabla (sin usar la palabra clave SQL "date" como nombre de columna.):

CREATE TABLE tbl(
  pid int
, the_date date
, PRIMARY KEY (pid, the_date)
);

Consulta:

SELECT pid, the_date
     , row_number() OVER (PARTITION BY pid, grp ORDER BY the_date) AS in_streak
FROM  (
   SELECT *
        , the_date - '2000-01-01'::date
        - row_number() OVER (PARTITION BY pid ORDER BY the_date) AS grp
   FROM   tbl
) sub
ORDER  BY pid, the_date;

Restar una date de otra date produce un integer . Dado que está buscando días consecutivos, cada fila siguiente sería mayor en uno . Si restamos row_number() a partir de ahí, toda la racha termina en el mismo grupo (grp ) por pid . Entonces es sencillo repartir números por grupo.

grp se calcula con dos restas, que deberían ser las más rápidas. Una alternativa igualmente rápida podría ser:

the_date - row_number() OVER (PARTITION BY pid ORDER BY the_date) * interval '1d' AS grp

Una multiplicación, una resta. La concatenación de cadenas y la conversión son más costosas. Prueba con EXPLAIN ANALYZE .

No olvides particionar por pid adicionalmente en ambos pasos, o sin querer mezclará grupos que deberían estar separados.

Usar una subconsulta, ya que suele ser más rápida que un CTE . No hay nada aquí que una simple subconsulta no pueda hacer.

Y ya que lo mencionaste:dense_rank() obviamente no necesario aquí. Básico row_number() hace el trabajo.