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

Xác định Xếp hạng dựa trên Nhiều Cột trong MySQL

Trong Bảng gốc (truy vấn con bên trong FROM ), chúng tôi sắp xếp dữ liệu của mình sao cho tất cả các hàng có cùng user_id các giá trị kết hợp với nhau, với việc sắp xếp thêm giữa chúng dựa trên game_detail theo thứ tự giảm dần.

Bây giờ, chúng tôi sử dụng tập kết quả này và sử dụng CASE..WHEN có điều kiện biểu thức để đánh giá việc đánh số hàng. Nó sẽ giống như một kỹ thuật Looping (mà chúng tôi sử dụng trong mã ứng dụng, ví dụ:PHP). Chúng tôi sẽ lưu trữ các giá trị của hàng trước đó trong các biến do Người dùng xác định, sau đó kiểm tra (các) giá trị của hàng hiện tại so với hàng trước đó. Cuối cùng, chúng tôi sẽ chỉ định số hàng cho phù hợp.

Chỉnh sửa: Dựa trên MySQL tài liệu và quan sát của @Gordon Linoff:

Thứ tự đánh giá cho các biểu thức liên quan đến biến người dùng được xác định. Ví dụ:không có gì đảm bảo rằng SELECT @a, @a: [email protected] + 1 đánh giá @a trước và sau đó thực hiện nhiệm vụ.

Chúng tôi sẽ cần đánh giá số hàng và chỉ định user_id giá trị thành @u biến trong cùng một biểu thức.

SET @r := 0, @u := 0; 
SELECT
  @r := CASE WHEN @u = dt.user_id 
                  THEN @r + 1
             WHEN @u := dt.user_id /* Notice := instead of = */
                  THEN 1 
        END AS user_game_rank, 
  dt.user_id, 
  dt.game_detail, 
  dt.game_id 

FROM 
( SELECT user_id, game_id, game_detail
  FROM game_logs 
  ORDER BY user_id, game_detail DESC 
) AS dt 

Kết quả

| user_game_rank | user_id | game_detail | game_id |
| -------------- | ------- | ----------- | ------- |
| 1              | 6       | 260         | 11      |
| 2              | 6       | 100         | 10      |
| 1              | 7       | 1200        | 10      |
| 2              | 7       | 500         | 11      |
| 3              | 7       | 260         | 12      |
| 4              | 7       | 50          | 13      |

Xem trên DB Fiddle

Một lưu ý thú vị từ MySQL Documents , mà tôi đã khám phá gần đây:

Các bản phát hành trước của MySQL cho phép gán một giá trị cho biến auser trong các câu lệnh không phải SET. Chức năng này được hỗ trợ trong MySQL 8.0 để tương thích ngược nhưng có thể bị hủy bỏ trong bản phát hành MySQL trong tương lai.

Ngoài ra, cảm ơn một thành viên SO khác, đã xem blog này của MySQL Team: https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/

Nhận xét chung là sử dụng ORDER BY với đánh giá của các biến người dùng trong cùng một khối truy vấn, không đảm bảo rằng các giá trị sẽ luôn đúng. Như, trình tối ưu hóa MySQL có thể vào đúng vị trí và thay đổi giả định của chúng tôi thứ tự đánh giá.

Cách tốt nhất cho vấn đề này là nâng cấp lên MySQL 8+ và sử dụng Row_Number() chức năng:

Giản đồ (MySQL v8.0)

SELECT user_id, 
       game_id, 
       game_detail, 
       ROW_NUMBER() OVER (PARTITION BY user_id 
                          ORDER BY game_detail DESC) AS user_game_rank 
FROM game_logs 
ORDER BY user_id, user_game_rank;

Kết quả

| user_id | game_id | game_detail | user_game_rank |
| ------- | ------- | ----------- | -------------- |
| 6       | 11      | 260         | 1              |
| 6       | 10      | 100         | 2              |
| 7       | 10      | 1200        | 1              |
| 7       | 11      | 500         | 2              |
| 7       | 12      | 260         | 3              |
| 7       | 13      | 50          | 4              |

Xem trên DB Fiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách thay đổi múi giờ máy chủ MySQL

  2. Chuyển từ MySQL sang PostgreSQL - Điều bạn nên biết

  3. Cách lặp qua tập kết quả mysql

  4. Laravel:kết nối động với cơ sở dữ liệu

  5. Hoạt động MySQL quá mức