A brechas-e-islas 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 :