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