Terdapat jadualmessages
yang mengandungi data seperti ini:
Id Name Other_Columns ------------------------- 1 A A_data_1 2 A A_data_2 3 A A_data_3 4 B B_data_1 5 B B_data_2 6 C C_data_1
Jika saya menjalankan pertanyaan select * from messages group by name
, hasil yang saya akan dapat ialah:
1 A A_data_1 4 B B_data_1 6 C C_data_1
Apakah pertanyaan yang akan mengembalikan hasil berikut?
3 A A_data_3 5 B B_data_2 6 C C_data_1
Maksudnya, rekod terakhir dalam setiap kumpulan hendaklah dikembalikan.
Pada masa ini, ini adalah pertanyaan yang saya gunakan:
SELECT * FROM (SELECT * FROM messages ORDER BY id DESC) AS x GROUP BY name
Tetapi ini nampaknya sangat tidak cekap. Adakah terdapat cara lain untuk mencapai hasil yang sama?
UPD: 31-03-2017, versi 5.7.5 MySQL mendayakan suis ONLY_FULL_GROUP_BY secara lalai (jadi pertanyaan GROUP BY bukan deterministik dilumpuhkan). Selain itu, mereka mengemas kini pelaksanaan GROUP BY dan penyelesaiannya mungkin tidak berfungsi seperti yang diharapkan walaupun dengan suis dilumpuhkan. Perlu menyemaknya.
Penyelesaian Bill Karwin di atas berfungsi dengan baik apabila bilangan item dalam kumpulan agak kecil, tetapi apabila kumpulan agak besar prestasi pertanyaan menjadi lemah kerana penyelesaian memerlukan lebih kurang n*n/2 + n/2 Hanya bandingkan
IS NULL
IS NULL
.Saya menguji pada jadual InnoDB yang mengandungi186844461182
kumpulan. Jadual ini mengandungi keputusan ujian untuk ujian berfungsi dan mempunyai18684446
行和1182
组的 InnoDB 表上进行了测试。该表包含功能测试的测试结果,并以(test_id, request_id)
作为主键。因此,test_id
是一个组,我正在为每个test_id
搜索最后一个request_id
baris dan(test_id, request_id)
sebagai kunci utama. Jadi,
ialah kumpulan dan saya sedang mencaritest_id
request_id- Penyelesaian Bill telah berjalan pada Dell e4310 saya selama beberapa jam sekarang, dan walaupun ia berjalan pada indeks penutup (oleh itu menggunakan indeks dalam EXPLAIN), saya tidak tahu bila ia akan lengkap.
Saya mempunyai beberapa penyelesaian lain berdasarkan idea yang sama: -
- Jika indeks pendasar ialah indeks BTREE (yang selalunya berlaku), maka pasangan
(group_id, item_value)
terbesar ialah nilai terakhir dalam setiap
Ini mengambil masa kira-kira 1.2 saat untuk data saya. 🎜 🎜🎜Penyelesaian 2🎜🎜 🎜Ini satu lagi penyelesaian yang mengambil masa kira-kira 19 saat untuk jam tangan saya: 🎜
terakhir untuk setiap
.test_id
(group_id, item_value)
对是每个group_id
中的最后一个值,即如果我们按降序遍历索引,则为每个group_id
group_id- , iaitu jika kita melintasi indeks dalam menurun pesanan, Maka ia adalah yang pertama daripada setiap
id_kumpulan
;
Jika kita membaca nilai yang diliputi oleh indeks, nilai dibaca dalam susunan indeks Setiap indeks secara tersirat mengandungi lajur kunci utama yang dilampirkan pada indeks tersebut (iaitu kunci utama berada dalam indeks penutup). Dalam penyelesaian di bawah saya beroperasi secara langsung pada kunci utama, dalam kes anda, anda hanya perlu menambah lajur kunci utama kepada hasilnya.
Dalam banyak kes, adalah lebih murah untuk mengumpul ID baris yang diperlukan dalam susunan yang dikehendaki dalam subkueri dan menggabungkan hasil subkueri kepada ID. Oleh kerana untuk setiap baris dalam hasil subquery, MySQL perlu melakukan pengambilan berdasarkan kunci utama, subquery akan dimasukkan ke dalam join dahulu, dan baris akan dikeluarkan mengikut susunan id dalam subquery (jika kita tinggalkan ORDER BY yang jelas untuk menyertai )
3 Cara MySQL Menggunakan Indeks
ialah artikel yang bagus untuk membantu anda memahami beberapa butiran.Penyelesaian 1
Ini sangat pantas, mengambil masa kira-kira 0.8 saat pada baris 18J+ saya:
Jika anda ingin menukar susunan kepada ASC, masukkannya dalam subkueri yang hanya mengembalikan id dan gunakannya sebagai subkueri untuk menyertai lajur yang lain:Ia juga mengembalikan ujian dalam susunan menurun. Ia jauh lebih perlahan kerana ia melakukan imbasan indeks penuh, tetapi ia memberi anda idea tentang cara mengeluarkan N baris maksimum untuk setiap kumpulan.
Kelemahan pertanyaan ini ialah cache pertanyaan tidak boleh menyimpan hasil cariannya.
MySQL 8.0 kini menyokong fungsi tetingkap, seperti hampir semua pelaksanaan SQL yang popular. Menggunakan sintaks standard ini, kita boleh menulis sehingga n pertanyaan bagi setiap kumpulan:
Ini dan kaedah mencari yang lain bilangan maksimum baris yang dikumpulkan diterangkan dalam manual MySQL.
Berikut ialah jawapan asal yang saya tulis untuk soalan ini pada tahun 2009:
Saya menulis penyelesaian seperti ini: