A mezery a ostrovy opravdu problém.
Za předpokladu:
- "Streaky" nejsou přerušovány řadami od ostatních hráčů.
- Všechny sloupce jsou definovány
NOT NULL
. (Jinak musíte udělat více.)
To by mělo být nejjednodušší a nejrychlejší, protože potřebuje pouze dva rychlé row_number()
funkce okna
:
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 zde
Pomocí názvu sloupce ts
místo time
, což je rezervované slovo
ve standardním SQL. V Postgresu je to povoleno, ale s omezeními a stále je to špatný nápad používat to jako identifikátor.
„Trik“ spočívá v odečtení čísel řádků tak, aby po sobě jdoucí řádky spadaly do stejné skupiny (grp
) za (player_id, points)
. Potom filtrujte ty se 100 body, agregujte je podle skupiny a vraťte pouze nejdelší a nejnovější výsledek na hráče.
Základní vysvětlení techniky:
Můžeme použít GROUP BY
a DISTINCT ON
ve stejném SELECT
, GROUP BY
se použije před DISTINCT ON
. Zvažte sled událostí v SELECT
dotaz:
O DISTINCT ON
: