Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Tentukan Peringkat berdasarkan Beberapa Kolom di MySQL

Dalam Tabel Turunan (subquery di dalam FROM klausa), kami mengurutkan data kami sedemikian rupa sehingga semua baris memiliki user_id yang sama nilai datang bersama-sama, dengan penyortiran lebih lanjut di antara mereka berdasarkan game_detail dalam urutan menurun.

Sekarang, kami menggunakan kumpulan hasil ini dan menggunakan CASE..WHEN bersyarat ekspresi untuk mengevaluasi penomoran baris. Ini akan seperti teknik Looping (yang kita gunakan dalam kode aplikasi, misalnya:PHP). Kami akan menyimpan nilai baris sebelumnya dalam variabel yang ditentukan Pengguna, dan kemudian memeriksa nilai baris saat ini terhadap baris sebelumnya. Akhirnya, kami akan menetapkan nomor baris yang sesuai.

Sunting: Berdasarkan dokumen MySQL dan pengamatan @Gordon Linoff:

Urutan evaluasi untuk ekspresi yang melibatkan variabel pengguna tidak ditentukan. Misalnya, tidak ada jaminan bahwa SELECT @a, @a:[email protected] +1mengevaluasi @a terlebih dahulu lalu melakukan tugas.

Kita perlu mengevaluasi nomor baris dan menetapkan user_id nilai ke @u variabel dalam ekspresi yang sama.

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 

Hasil

| 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      |

Lihat di DB Fiddle

Catatan menarik dari MySQL Dokumen , yang saya temukan baru-baru ini:

Rilis MySQL sebelumnya memungkinkan untuk menetapkan nilai ke variabel pengguna dalam pernyataan selain SET. Fungsionalitas ini didukung di MySQL 8.0 untuk kompatibilitas mundur tetapi dapat dihapus pada rilis MySQL mendatang.

Juga, terima kasih kepada sesama anggota SO, menemukan blog ini oleh Tim MySQL:https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/

Pengamatan umum adalah bahwa menggunakan ORDER BY dengan evaluasi variabel pengguna di blok kueri yang sama, tidak memastikan bahwa nilainya akan selalu benar. Sebagai, pengoptimal MySQL mungkin datang ke tempatnya dan ubah yang diduga urutan evaluasi.

Pendekatan terbaik untuk masalah ini adalah memutakhirkan ke MySQL 8+ dan memanfaatkan Row_Number() fungsi:

Skema (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;

Hasil

| 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              |

Lihat di 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. Belajar MySQL / MariaDB untuk Pemula – Bagian 1

  2. Apakah transaksi bersarang diperbolehkan di MySQL?

  3. Contoh MySQL REGEXP

  4. JSON_MERGE_PRESERVE() – Menggabungkan Beberapa Dokumen JSON di MySQL

  5. Cara Menggunakan Tampilan di Database MySQL