sql >> Databasteknik >  >> RDS >> PostgreSQL

Hitta den längsta raden av perfekta poäng per spelare

En problem verkligen.

Förutsatt:

  • "Streaks" avbryts inte av rader från andra spelare.
  • Alla kolumner är definierade NOT NULL . (Annars måste du göra mer.)

Detta bör vara enklast och snabbast eftersom det bara behöver två snabba row_number() fönsterfunktioner :

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<>fiol här

Använder kolumnnamnet ts istället för time , som är ett reserverat ord i standard SQL. Det är tillåtet i Postgres, men med begränsningar och det är fortfarande en dålig idé att använda det som identifierare.

"Knepet" är att subtrahera radnummer så att på varandra följande rader faller i samma grupp (grp ) per (player_id, points) . filtrera de med 100 poäng, samla per grupp och returnera endast det längsta, senaste resultatet per spelare.
Grundläggande förklaring till tekniken:

Vi kan använda GROUP BY och DISTINCT ON i samma SELECT , GROUP BY tillämpas före DISTINCT ON . Tänk på händelseförloppet i en SELECT fråga:

Om DISTINCT ON :



  1. Orsakas av:java.sql.SQLException:Teckenkodningen 'utf8mb4' stöds inte

  2. IO-fel:Sockets läsning tog timeout. Vilka är orsakerna?

  3. Kolumn Namn som börjar med en siffra?

  4. C++ Program som kommunicerar med MySQL Database