PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Finden Sie die längste Serie perfekter Ergebnisse pro Spieler

Ein in der Tat ein Problem.

Annahme:

  • "Streaks" werden nicht durch Reihen anderer Spieler unterbrochen.
  • Alle Spalten sind NOT NULL definiert . (Andernfalls müssen Sie mehr tun.)

Dies sollte am einfachsten und schnellsten sein, da es nur zwei schnelle row_number() Fensterfunktionen :

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 hier

Verwenden Sie den Spaltennamen ts statt time , das ein reserviertes Wort ist in Standard-SQL. Es ist in Postgres erlaubt, aber mit Einschränkungen, und es ist immer noch eine schlechte Idee, es als Bezeichner zu verwenden.

Der „Trick“ besteht darin, Zeilennummern zu subtrahieren, sodass aufeinanderfolgende Zeilen in dieselbe Gruppe fallen (grp ) pro (player_id, points) . Dann Filtere die mit 100 Punkten, sammle pro Gruppe und gib nur das längste, neueste Ergebnis pro Spieler zurück.
Grundlegende Erklärung für die Technik:

Wir können GROUP BY verwenden und DISTINCT ON im gleichen SELECT , GROUP BY wird vorher angewendet DISTINCT ON . Betrachten Sie die Abfolge von Ereignissen in einem SELECT Abfrage:

Über DISTINCT ON :