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

Encuentra la racha más larga de puntajes perfectos por jugador

A problema de hecho.

Suponiendo:

  • Las "rachas" no se ven interrumpidas por filas de otros jugadores.
  • Todas las columnas están definidas NOT NULL . (Si no, tienes que hacer más.)

Esto debería ser más simple y rápido, ya que solo necesita dos rápidos row_number() funciones de ventana :

SELECT DISTINCT ON (player_id)
       player_id, count(*) AS seq_len, min(ts) AS time_began
FROM  (
   SELECT player_id, points, ts
        , row_number() OVER (PARTITION BY player_id ORDER BY ts) 
        - row_number() OVER (PARTITION BY player_id, points ORDER BY ts) AS grp
   FROM   tbl
   ) sub
WHERE  points = 100
GROUP  BY player_id, grp  -- omit "points" after WHERE points = 100
ORDER  BY player_id, seq_len DESC, time_began DESC;

db<>fiddle aquí

Usando el nombre de columna ts en lugar de time , que es una palabra reservada en SQL estándar. Está permitido en Postgres, pero con limitaciones y sigue siendo una mala idea usarlo como identificador.

El "truco" es restar números de fila para que las filas consecutivas caigan en el mismo grupo (grp ) por (player_id, points) . Entonces filtre los que tengan 100 puntos, agregue por grupo y devuelva solo el resultado más largo y más reciente por jugador.
Explicación básica de la técnica:

Podemos usar GROUP BY y DISTINCT ON en el mismo SELECT , GROUP BY se aplica antes DISTINCT ON . Considere la secuencia de eventos en un SELECT consulta:

Acerca de DISTINCT ON :