Dapatkan rekod terakhir setiap kumpulan menggunakan MySQL
P粉736935587
2023-08-20 11:48:53
<p>Terdapat jadual yang dipanggil <kod>mesej</code>
<pre class="brush:php;toolbar:false;">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</pre>
<p>Jika saya menjalankan pertanyaan <kod>pilih * daripada kumpulan mesej mengikut nama</kod>, saya mendapat keputusan berikut: </p>
<pre class="brush:php;toolbar:false;">1 A A_data_1
4 B B_data_1
6 C C_data_1</pre>
<p>Pertanyaan yang manakah akan mengembalikan hasil berikut? </p>
<pre class="brush:php;toolbar:false;">3 A A_data_3
5 B B_data_2
6 C C_data_1</pre>
<p>Iaitu, rekod terakhir dalam setiap kumpulan hendaklah dikembalikan. </p>
<p>Pada masa ini, ini ialah pertanyaan yang saya gunakan: </p>
<pre class="brush:php;toolbar:false;">SELECT
*
DARI (PILIH
*
DARIPADA mesej
PESANAN OLEH id DESC) SEBAGAI x
KUMPULAN MENGIKUT nama</pra>
<p>Tetapi ini nampaknya tidak cekap. Adakah terdapat cara lain untuk mencapai hasil yang sama? </p>
UPD: 31-03-2017, versi MySQL 5.7.5 mempunyai suis ONLY_FULL_GROUP_BY didayakan secara lalai (oleh itu, pertanyaan GROUP BY bukan deterministik dilumpuhkan). Selain itu, mereka mengemas kini pelaksanaan GROUP BY dan penyelesaian mungkin tidak lagi berfungsi seperti yang diharapkan walaupun dengan suis dilumpuhkan. Pemeriksaan diperlukan.
Penyelesaian Bill Karwin berfungsi dengan baik apabila bilangan item dalam kumpulan adalah kecil, tetapi prestasi pertanyaan menjadi lebih teruk apabila kumpulan lebih besar kerana penyelesaian memerlukan kira-kira
n*n/2 + n/2
次IS NULL
perbandingan.Saya termasuk dalam
18684446
行和1182
个组的InnoDB表上进行了测试。该表包含功能测试的测试结果,并且(test_id, request_id)
是主键。因此,test_id
是一个组,我正在寻找每个test_id
的最后一个request_id
.Penyelesaian Bill telah berjalan pada Dell e4310 saya selama beberapa jam sekarang, saya tidak tahu bila ia akan lengkap, walaupun ia beroperasi pada indeks tertutup (oleh itu EXPLAIN ditunjukkan
using index
).Saya ada beberapa lagi penyelesaian berdasarkan idea yang sama:
group_id
中的最大(group_id, item_value)
对就是每个group_id
的最后一个值,如果我们按降序遍历索引,则是每个group_id
3 cara MySQL menggunakan indeks ialah artikel yang bagus untuk memahami beberapa butiran.
Penyelesaian 1
Penyelesaian ini sangat pantas, mengambil masa kira-kira 0.8 saat untuk 18 juta+ baris data saya:
Jika anda ingin menukar susunan kepada menaik, masukkannya dalam subkueri, pulangkan hanya ID dan sertainya sebagai subkueri dengan lajur lain:
Untuk data saya, penyelesaian ini mengambil masa kira-kira 1.2 saat.
Penyelesaian 2
Ini adalah penyelesaian lain, untuk jadual saya ia mengambil masa kira-kira 19 saat:
Ia juga mengembalikan keputusan ujian dalam susunan menurun. Ia lebih perlahan kerana ia melakukan imbasan indeks penuh, tetapi ia boleh memberi anda idea tentang cara untuk mengeluarkan N baris maksimum untuk setiap kumpulan.
Kelemahan pertanyaan ini ialah keputusannya tidak boleh dicache oleh pertanyaan.
MySQL 8.0 kini menyokong Fungsi tetingkap, begitu juga dengan hampir semua pelaksanaan SQL yang popular. Menggunakan sintaks standard ini, kita boleh menulis pertanyaan maks-n-per-kumpulan:
ManualMySQL menunjukkan kaedah ini dan kaedah lain untuk mencari baris terbesar terkumpul.
Berikut ialah jawapan asal yang saya tulis untuk soalan ini pada tahun 2009:
Saya menulis penyelesaian seperti ini:
Berkenaan prestasi, bergantung pada sifat data, salah satu penyelesaian mungkin lebih baik. Oleh itu, anda harus menguji kedua-dua pertanyaan dan memilih yang lebih baik berdasarkan prestasi pangkalan data anda.
Sebagai contoh, saya mempunyai salinan StackOverflow August Data Dump. Saya akan menggunakannya untuk penanda aras. Terdapat 1,114,357 baris data dalam jadual
Posts
. Ini sedang berjalan MySQL 5.0.75 pada Macbook Pro 2.40GHz saya.Saya akan menulis pertanyaan untuk mencari siaran terkini untuk ID pengguna yang diberikan (saya).
Pertama digunakan teknik Eric menggunakan
GROUP BY
dalam subkueri:Malah
EXPLAIN
analisis mengambil masa lebih daripada 16 saat:Kini menggunakan
LEFT JOIN
menggunakan teknik saya menghasilkan hasil pertanyaan yang sama:EXPLAIN
Analisis menunjukkan bahawa kedua-dua jadual boleh menggunakan indeksnya:Ini adalah DDL jadual
Posts
saya:Nota kepada pengulas: Jika anda ingin menjalankan penanda aras lain menggunakan versi MySQL yang berbeza, set data yang berbeza atau reka bentuk jadual yang berbeza, sila lakukan sendiri. Saya telah menunjukkan teknik di atas. Tujuan Stack Overflow adalah untuk menunjukkan kepada anda cara melakukan kerja pembangunan perisian, bukan untuk melakukan semua kerja untuk anda.