Một khoảng trống và đảo thực sự có vấn đề.
Giả sử:
- "Vệt" không bị gián đoạn bởi các hàng từ những người chơi khác.
- Tất cả các cột được xác định
NOT NULL
. (Nếu không, bạn phải làm nhiều việc hơn.)
Điều này phải đơn giản và nhanh nhất vì nó chỉ cần hai row_number()
chức năng cửa sổ
:
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 tại đây
Sử dụng tên cột ts
thay vì time
, là một từ dành riêng
trong SQL chuẩn. Nó được phép trong Postgres, nhưng có những hạn chế và bạn vẫn nên sử dụng nó làm định danh.
"Thủ thuật" là trừ số hàng để các hàng liên tiếp nằm trong cùng một nhóm (grp
) mỗi (player_id, points)
. Sau đó lọc những người có 100 điểm, tổng hợp cho mỗi nhóm và chỉ trả lại kết quả dài nhất, gần đây nhất cho mỗi người chơi.
Giải thích cơ bản cho kỹ thuật:
Chúng ta có thể sử dụng GROUP BY
và DISTINCT ON
trong cùng một SELECT
, GROUP BY
được áp dụng trước đây DISTINCT ON
. Xem xét chuỗi sự kiện trong SELECT
truy vấn:
Giới thiệu về DISTINCT ON
: