Mengapa tidak bekerja dengan GROUP BY
SELECT *
tidak dapat digunakan dengan GROUP BY
; itu adalah SQL yang tidak valid. GROUP BY
tidak memilih baris tabel. Ini membuat grup baris menggunakan ekspresi yang disediakan kemudian, dari setiap grup, ini menghasilkan catatan baru dan menghitung setiap kolom dari catatan baru ini menggunakan nilai yang terlibat dalam ekspresi.
Kolom yang muncul di SELECT
klausa harus memenuhi salah satu aturan berikut:
- juga muncul di
GROUP BY
klausa; - digunakan dengan
GROUP BY
fungsi agregat ; - bergantung secara fungsional pada kolom yang muncul di
GROUP BY
klausa.
Sementara *
adalah jalan pintas untuk semua nama kolom dari tabel yang digunakan oleh kueri, untuk kueri Anda hanya user
kolom memenuhi salah satu persyaratan di atas.
Sebelum versi 5.7.5
MySQL tidak menerapkan aturan ketiga di atas. Digunakan untuk menerima kueri yang berisi SELECT
kolom klausa yang tidak mengikuti salah satu GROUP BY
persyaratan. Nilai yang dikembalikan oleh kueri untuk kolom tersebut adalah tidak tentu
.
Sejak versi 5.7.5, MySQL menolak GROUP BY
kueri yang memenuhi persyaratan.
Solusinya
Bagaimanapun, solusi untuk masalah Anda tidak melibatkan GROUP BY
. Ini dapat dilakukan dengan mudah menggunakan LEFT JOIN
dengan kondisi yang benar:
SELECT lc.*
FROM comments lc # 'lc' from 'last comment'
LEFT JOIN comments nc # 'nc' from 'newer comment'
ON lc.user = nc.user # both comments belong to the same user
AND lc.id < nc.id # 'nc' is newer than 'lc'
WHERE nc.id IS NULL # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10
Cara kerjanya
Ini bergabung dengan tabel comments
, alias sebagai lc
("lc" dari "komentar terakhir" pengguna) terhadap dirinya sendiri, alias sebagai nc
("nc" dari "komentar baru"). Klausa join cocok dengan setiap entri lc
dengan semua entri nc
milik pengguna yang sama (lc.user = nc.user
) dan lebih baru (lc.id < nc.id
; Saya berasumsi bahwa ID diberikan secara berurutan dan komentar yang lebih baru memiliki nilai yang lebih besar untuk id
).
Penggunaan LEFT JOIN
memastikan bahwa setiap baris lc
muncul di hasil penggabungan, bahkan ketika tidak ada baris yang cocok ditemukan di nc
(karena tidak ada komentar yang lebih baru dari pengguna yang sama). Dalam hal ini, NULL
digunakan sebagai ganti bidang nc
. WHERE
klausa tetap dalam hasil akhir, atur hanya baris yang memiliki NULL
di nc.id
; ini berarti di lc
sebagian berisi komentar terbaru dari setiap pengguna.
SELECT
klausa berisi semua bidang lc
(yang dari nc
semuanya NULL
, omong-omong). ORDER BY
klausa dapat digunakan untuk mengurutkan kumpulan hasil. ORDER BY lc.id DESC
menempatkan komentar terbaru terlebih dahulu dan LIMIT
klausa menjaga hasil disetel ke ukuran yang layak.