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 :