Salah satu opsi adalah menggunakan variabel peringkat, seperti yang berikut:
SELECT first_name,
age,
gender,
@curRank := @curRank + 1 AS rank
FROM person p, (SELECT @curRank := 0) r
ORDER BY age;
Bagian ini (SELECT @curRank := 0)
memungkinkan inisialisasi variabel tanpa memerlukan SET
perintah terpisah .
Kasus cobaan:
CREATE TABLE person (id int, first_name varchar(20), age int, gender char(1));
INSERT INTO person VALUES (1, 'Bob', 25, 'M');
INSERT INTO person VALUES (2, 'Jane', 20, 'F');
INSERT INTO person VALUES (3, 'Jack', 30, 'M');
INSERT INTO person VALUES (4, 'Bill', 32, 'M');
INSERT INTO person VALUES (5, 'Nick', 22, 'M');
INSERT INTO person VALUES (6, 'Kathy', 18, 'F');
INSERT INTO person VALUES (7, 'Steve', 36, 'M');
INSERT INTO person VALUES (8, 'Anne', 25, 'F');
Hasil:
+------------+------+--------+------+
| first_name | age | gender | rank |
+------------+------+--------+------+
| Kathy | 18 | F | 1 |
| Jane | 20 | F | 2 |
| Nick | 22 | M | 3 |
| Bob | 25 | M | 4 |
| Anne | 25 | F | 5 |
| Jack | 30 | M | 6 |
| Bill | 32 | M | 7 |
| Steve | 36 | M | 8 |
+------------+------+--------+------+
8 rows in set (0.02 sec)
partition by gender
bagian dari fungsi analitis (yang "angka" nilai peringkat per jenis kelamin bukan untuk hasil keseluruhan)Berikut adalah solusi umum yang memberikan peringkat padat partisi ke baris. Ini menggunakan variabel pengguna:
Perhatikan bahwa tugas variabel ditempatkan di dalam
CASE
ekspresi. Ini (secara teori) menangani urutan masalah evaluasi. ItuIS NOT NULL
ditambahkan untuk menangani konversi tipe data dan masalah korsleting.PS: Dapat dengan mudah dikonversi menjadi nomor baris di atas partisi dengan menghapus semua kondisi yang memeriksa dasi.
Demo di db <> biola
sumber
ELSE @rank_count := @rank_count + 1
ORDER BY gender, age DESC
?Sementara peringkat jawaban yang paling banyak dipilih, itu tidak mempartisi, Anda bisa melakukan sendiri Gabung untuk mendapatkan semuanya juga dipartisi:
Gunakan Kasing
Jawaban :
sumber
Tweak dari versi Daniel untuk menghitung persentil bersama dengan peringkat. Juga dua orang dengan nilai yang sama akan mendapatkan peringkat yang sama.
Hasil kueri untuk data sampel -
sumber
Kombinasi jawaban Daniel dan Salman. Namun pangkat tidak akan memberikan urutan berlanjut dengan ikatan ada. Alih-alih itu melompat peringkat ke berikutnya. Jadi maksimum selalu mencapai jumlah baris.
Skema dan Uji Kasus:
Keluaran:
sumber
Dimulai dengan MySQL 8, Anda akhirnya dapat menggunakan fungsi jendela juga di MySQL: https://dev.mysql.com/doc/refman/8.0/id/window-functions.html
Permintaan Anda dapat ditulis dengan cara yang persis sama:
sumber
@Sam, maksud Anda sangat bagus dalam konsep tapi saya pikir Anda salah mengerti apa yang dikatakan oleh dokumen MySQL pada halaman yang direferensikan - atau saya salah paham :-) - dan saya hanya ingin menambahkan ini sehingga jika seseorang merasa tidak nyaman dengan @ Jawaban Daniel mereka akan lebih diyakinkan atau setidaknya menggali lebih dalam.
Anda lihat di
"@curRank := @curRank + 1 AS rank"
dalamSELECT
itu bukan "satu pernyataan", itu adalah satu "atom" bagian dari pernyataan itu sehingga harus aman.Dokumen yang Anda referensi melanjutkan untuk memperlihatkan contoh-contoh di mana variabel yang ditentukan pengguna yang sama dalam 2 bagian (atom) pernyataan, misalnya,
"SELECT @curRank, @curRank := @curRank + 1 AS rank"
,.Orang mungkin berpendapat bahwa
@curRank
ini digunakan dua kali dalam jawaban @ Daniel: (1)"@curRank := @curRank + 1 AS rank"
dan (2)"(SELECT @curRank := 0) r"
tetapi karena penggunaan kedua adalah bagian dariFROM
klausa, saya cukup yakin itu dijamin untuk dievaluasi terlebih dahulu; pada dasarnya membuatnya menjadi pernyataan kedua, dan sebelumnya.Bahkan, pada halaman dokumen MySQL yang sama yang Anda referensikan, Anda akan melihat solusi yang sama di komentar - itu bisa dari mana @Daniel mendapatkannya; ya, saya tahu bahwa itu adalah komentar tetapi itu adalah komentar di halaman dokumen resmi dan itu memang membawa beban.
sumber
Solusi paling lurus ke depan untuk menentukan peringkat nilai yang diberikan adalah dengan menghitung jumlah nilai sebelum itu. Misalkan kita memiliki nilai-nilai berikut:
30
nilai dipertimbangkan ke-340
nilai dianggap ke-6 (peringkat) atau ke - 4 (peringkat padat)Sekarang kembali ke pertanyaan awal. Berikut adalah beberapa contoh data yang diurutkan seperti dijelaskan dalam OP (peringkat yang diharapkan ditambahkan di sebelah kanan):
Untuk menghitung
RANK() OVER (PARTITION BY Gender ORDER BY Age)
untuk Sarah , Anda dapat menggunakan kueri ini:Untuk menghitung
RANK() OVER (PARTITION BY Gender ORDER BY Age)
untuk Semua baris Anda dapat menggunakan query ini:Dan inilah hasilnya (nilai gabungan ditambahkan di sebelah kanan):
sumber
Jika Anda ingin peringkat hanya satu orang, Anda dapat melakukan hal berikut:
Peringkat ini sesuai dengan fungsi RANK oracle (Di mana jika Anda memiliki orang dengan usia yang sama mereka mendapatkan peringkat yang sama, dan peringkat setelah itu adalah non-berturut-turut).
Ini sedikit lebih cepat daripada menggunakan salah satu solusi di atas dalam subquery dan memilih dari itu untuk mendapatkan peringkat satu orang.
Ini dapat digunakan untuk memberi peringkat pada semua orang tetapi lebih lambat dari solusi di atas.
sumber
Person
tabel bertambah. Ini lebih lambat O (n ^ 2) vs O (n) .Untuk menghindari " namun " dalam jawaban Erandac dalam kombinasi jawaban Daniel dan Salman, orang dapat menggunakan salah satu dari "pemecahan masalah partisi" berikut ini
Peringkat partisi dalam varian ke-3 dalam cuplikan kode ini akan menghasilkan angka peringkat berkelanjutan. ini akan mengarah pada struktur data yang mirip dengan
rank() over partition by
hasilnya. Sebagai contoh, lihat di bawah. Secara khusus, partisiSequence akan selalu dimulai dengan 1 untuk setiap partisiRank baru , menggunakan metode ini:sumber
sumber