Hal pertama yang harus dijelaskan adalah bahwa SQL bukanlah MySQL.
Dalam SQL standar tidak diperbolehkan untuk mengelompokkan berdasarkan subset dari bidang non-agregat. Alasannya sangat sederhana. Misalkan saya menjalankan kueri ini:
SELECT color, owner_name, COUNT(*) FROM cars
GROUP BY color
Permintaan itu tidak masuk akal. Bahkan mencoba menjelaskannya tidak mungkin. Yang pasti itu adalah memilih warna dan menghitung jumlah mobil per warna. Namun, itu juga menambahkan owner_name
bidang dan bisa ada banyak pemilik untuk warna tertentu, seperti kasus White
warna. Jadi kalau bisa banyak owner_name
nilai untuk satu color
yang kebetulan merupakan satu-satunya bidang di GROUP BY
klausa... lalu owner_name
. yang mana akan dikembalikan?
Jika diperlukan untuk mengembalikan owner_name
maka beberapa jenis kriteria harus ditambahkan untuk hanya memilih salah satu dari mereka, misalnya, yang pertama menurut abjad, yang dalam hal ini adalah John
. Kriteria itu akan menghasilkan penambahan fungsi agregat MIN(owner_name)
lalu kueri akan masuk akal lagi karena akan dikelompokkan berdasarkan, setidaknya, semua bidang yang tidak digabungkan dalam pernyataan pilih.
Seperti yang Anda lihat, ada alasan yang jelas dan praktis untuk SQL standar menjadi tidak fleksibel dalam pengelompokan. Jika tidak, Anda bisa menghadapi situasi canggung di mana nilai kolom tidak dapat diprediksi, dan itu bukan kata yang bagus, terutama jika kueri yang dijalankan menunjukkan transaksi rekening bank Anda.
Karena itu, lalu mengapa MySQL mengizinkan kueri yang mungkin tidak masuk akal? Dan lebih buruk lagi, kesalahan dalam kueri di atas bisa saja terdeteksi secara sintaksis! Jawaban singkatnya adalah:kinerja. Jawaban panjangnya adalah bahwa ada situasi tertentu di mana, berdasarkan hubungan data, mendapatkan nilai yang tidak terduga dari grup akan menghasilkan nilai yang dapat diprediksi.
Jika Anda belum mengetahuinya, satu-satunya cara Anda dapat memprediksi nilai yang akan Anda peroleh dari mengambil elemen yang tidak dapat diprediksi dari suatu grup adalah jika semua elemen dalam grup tersebut sama. Contoh yang jelas dari situasi ini adalah dalam contoh kueri dalam pertanyaan Anda yang sama. Lihat bagaimana owner_id
dan owner_name
berhubungan dalam tabel. Jelas bahwa diberikan owner_id
, misalnya 2
, Anda hanya dapat memiliki satu owner_name
yang berbeda . Bahkan memiliki banyak baris, dengan memilih salah satu, Anda akan mendapatkan Mike
hasilnya. Dalam jargon database formal ini dapat dijelaskan sebagai owner_id
secara fungsional menentukan owner_name
.
Mari kita lihat lebih dekat kueri MySQL yang berfungsi penuh itu:
SELECT owner_id, owner_name, COUNT(*) total FROM cars
GROUP BY owner_id
Diberikan owner_id
ini akan mengembalikan owner_name
yang sama , jadi tambahkan ke GROUP BY
klausa tidak akan menghasilkan lebih banyak baris yang dikembalikan. Bahkan menambahkan fungsi gabungan MAX(owner_name)
tidak akan menghasilkan lebih sedikit baris yang dikembalikan. Data yang dihasilkan akan sama persis. Dalam kedua kasus, kueri akan segera diubah menjadi kueri SQL standar hukum karena setidaknya semua bidang yang tidak teragregasi akan dikelompokkan. Jadi ada 3 pendekatan untuk mendapatkan hasil yang sama.
Namun, seperti yang saya sebutkan sebelumnya, pengelompokan non-standar ini memiliki keunggulan kinerja. Anda dapat memeriksa tautan yang sangat diremehkan di mana ini dijelaskan untuk lebih detail tetapi saya akan mengutip bagian yang paling penting:
Satu hal yang perlu disebutkan adalah bahwa hasilnya belum tentu salah melainkan tidak pasti . Dengan kata lain, mendapatkan hasil yang diharapkan tidak berarti Anda telah menulis kueri yang benar. Menulis kueri yang tepat akan selalu memberi Anda hasil yang diharapkan.
Seperti yang Anda lihat, mungkin ada baiknya menerapkan ekstensi MySQL ini ke GROUP BY
ayat. Bagaimanapun, jika ini belum 100% jelas maka ada aturan praktis yang akan memastikan bahwa pengelompokan Anda akan selalu benar:Selalu kelompokkan, setidaknya, dengan semua bidang non-agregat di klausa pilih . Anda mungkin menyia-nyiakan beberapa siklus CPU dalam situasi tertentu, tetapi ini lebih baik daripada mengembalikan tidak tentu hasil. Jika Anda masih takut tidak mengelompokkan dengan benar, maka ubah ONLY_FULL_GROUP_BY
Mode SQL bisa menjadi pilihan terakhir :)
Semoga pengelompokan Anda benar dan berkinerja... atau setidaknya benar.