PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tìm chuỗi điểm số hoàn hảo dài nhất trên mỗi người chơi

Một 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 BYDISTINCT 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 :



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sự cố tạo PostgreSQL Trigger

  2. Postgres trả về [null] thay vì [] cho array_agg của bảng tham gia

  3. Làm cách nào để chỉ cài đặt các công cụ máy khách cho PostgreSQL trên Windows?

  4. Cập nhật Bản ghi Hoạt động Tất cả Trường JSON

  5. Tìm các bản ghi mới cho mỗi n tháng qua trong PostgreSQL