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

Encontre a sequência mais longa de pontuações perfeitas por jogador


A problema mesmo.

Supondo:
  • "Streaks" não são interrompidos por linhas de outros jogadores.
  • Todas as colunas são definidas NOT NULL . (Caso contrário, você precisa fazer mais.)

Isso deve ser mais simples e rápido, pois precisa apenas de dois row_number() funções da janela :
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 aqui

Usando o nome da coluna ts em vez de time , que é uma palavra reservada em SQL padrão. É permitido no Postgres, mas com limitações e ainda é uma má ideia usá-lo como identificador.

O "truque" é subtrair os números das linhas para que as linhas consecutivas caiam no mesmo grupo (grp ) por (player_id, points) . Então filtre aqueles com 100 pontos, agregue por grupo e retorne apenas o resultado mais longo e mais recente por jogador.
Explicação básica para a técnica:

Podemos usar GROUP BY e DISTINCT ON no mesmo SELECT , GROUP BY é aplicado antes DISTINCT ON . Considere a sequência de eventos em um SELECT consulta:

Sobre DISTINCT ON :