Ada banyak cara untuk mencapai ini dengan fungsi yang ada. Anda dapat menggunakan fungsi jendela first_value()
dan last_value()
, dikombinasikan dengan DISTINCT
atau DISTINCT ON
untuk mendapatkannya tanpa bergabung dan subkueri:
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);
Perhatikan frame khusus untuk fungsi jendela !
Atau Anda dapat menggunakan fungsi agregat dasar dalam subquery dan BERGABUNG:
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;
Dengan asumsi (userid, rank)
yang unik , atau persyaratan Anda akan ambigu.
Shichinin bukan samurai
Per permintaan di komentar, sama hanya untuk tujuh baris terakhir per userid (atau sebanyak yang dapat ditemukan, jika ada lebih sedikit):
Sekali lagi, salah satu dari banyak cara yang mungkin. Tapi saya yakin ini salah satu yang terpendek:
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;
Perhatikan urutan pengurutan terbalik. Baris pertama adalah entri "terbaru". Saya merentangkan bingkai (maks.) 7 baris dan hanya memilih hasil untuk entri terbaru dengan DISTINCT ON
.