Existuje mnoho způsobů, jak toho dosáhnout pomocí stávajících funkcí. Můžete použít stávající funkce okna first_value()
a last_value()
v kombinaci s DISTINCT
nebo DISTINCT ON
získat jej bez spojení a poddotazů:
SELECT DISTINCT ON (userid)
userid
, last_value(rank) OVER w
- first_value(rank) OVER w AS rank_delta
FROM rankings
WINDOW w AS (PARTITION BY userid ORDER BY ts
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING);
Všimněte si vlastních rámců pro funkce okna !
Nebo můžete použít základní agregační funkce v dílčím dotazu a JOIN:
SELECT userid, r2.rank - r1.rank AS rank_delta
FROM (
SELECT userid
, min(ts) AS first_ts
, max(ts) AS last_ts
FROM rankings
GROUP BY 1
) sub
JOIN rankings r1 USING (userid)
JOIN rankings r2 USING (userid)
WHERE r1.ts = first_ts
AND r2.ts = last_ts;
Za předpokladu jedinečného (userid, rank)
nebo by vaše požadavky byly nejednoznačné.
Shichinin no samuraj
Na žádost v komentářích, totéž pouze pro posledních sedm řádků na ID uživatele (nebo tolik, kolik jich lze najít, pokud jich je méně):
Opět jeden z mnoha možných způsobů. Ale věřím, že tohle je jeden z nejkratších:
SELECT DISTINCT ON (userid)
userid
, first_value(rank) OVER w
- last_value(rank) OVER w AS rank_delta
FROM rankings
WINDOW w AS (PARTITION BY userid ORDER BY ts DESC
ROWS BETWEEN CURRENT ROW AND 7 FOLLOWING)
ORDER BY userid, ts DESC;
Všimněte si obráceného pořadí řazení. První řádek je „nejnovější“ záznam. Zahrnu rámec (max.) 7 řádků a vyberu pouze výsledky pro nejnovější záznam s DISTINCT ON
.