Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana cara GROUP BY dengan benar di MySQL?

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara terbaik untuk mencari sebagian kata dalam kumpulan data MySQL yang besar

  2. pengaturan lower_case_table_names di MySQL 8.0.12

  3. ERROR 1005 (HY000):Tidak dapat membuat tabel (errno:150)

  4. Bagaimana saya bisa mengubah baris menjadi data berbasis kolom berulang?

  5. Satu item kuis per halaman (program kuis php/mysql)