PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Trouvez la plus longue série de scores parfaits par joueur

A problème en effet.

En supposant :

  • Les "séries" ne sont pas interrompues par des rangées d'autres joueurs.
  • Toutes les colonnes sont définies NOT NULL . (Sinon, vous devez en faire plus.)

Cela devrait être le plus simple et le plus rapide car il ne nécessite que deux row_number() fonctions de fenêtre :

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<>violon ici

Utilisation du nom de colonne ts au lieu de time , qui est un mot réservé en SQL standard. C'est autorisé dans Postgres, mais avec des limitations et c'est toujours une mauvaise idée de l'utiliser comme identifiant.

Le "truc" consiste à soustraire les numéros de ligne afin que les lignes consécutives tombent dans le même groupe (grp ) par (player_id, points) . Alors filtrez ceux avec 100 points, regroupez par groupe et ne retournez que le résultat le plus long et le plus récent par joueur.
Explication de base de la technique :

Nous pouvons utiliser GROUP BY et DISTINCT ON dans le même SELECT , GROUP BY est appliqué avant DISTINCT ON . Considérez la séquence d'événements dans un SELECT requête :

À propos de DISTINCT ON :