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

MySQL:Total GROUP BY DENGAN ROLLUP rasa ingin tahu

Karena Anda tidak MEMILIH item yang Anda KELOMPKAN. Jika Anda mengatakan:

GROUP BY c.printable_name

Anda akan mendapatkan NULL yang diharapkan. Namun Anda mengelompokkan berdasarkan kolom yang berbeda sehingga MySQL tidak tahu bahwa printable_name mengambil bagian dalam grup rollup, dan memilih nilai lama apa pun dari kolom itu, dalam gabungan semua pendaftaran. (Jadi mungkin Anda akan melihat negara lain selain Uzbekistan.)

Ini adalah bagian dari masalah yang lebih luas dengan MySQL yang permisif pada apa yang dapat Anda PILIH dalam kueri GROUP BY. Misalnya, Anda dapat mengatakan:

SELECT gender FROM registrations GROUP BY country;

dan MySQL dengan senang hati akan memilih salah satu nilai gender untuk pendaftaran dari setiap negara, meskipun tidak ada hubungan sebab akibat langsung (alias "ketergantungan fungsional") antara negara dan gender. DBMS lain akan menolak perintah di atas dengan alasan bahwa tidak ada jaminan untuk satu jenis kelamin per negara.(*)

Sekarang, ini:

SELECT c.printable_name AS 'Country', count(*) AS '#' 
FROM registrations r 
INNER JOIN country c ON r.country = c.country_id 
GROUP BY country

tidak apa-apa, karena ada ketergantungan fungsional antara r.country dan c.printable_name (dengan asumsi Anda telah mendeskripsikan dengan benar country_id Anda sebagai KUNCI UTAMA).

Namun ekstensi WITH ROLLUP MySQL adalah sedikit peretasan dalam cara kerjanya. Pada tahap baris rollup di akhir, ia menjalankan seluruh hasil pra-pengelompokan yang ditetapkan untuk mengambil nilainya, dan lalu menyetel kolom grup-demi ke NULL. Itu juga tidak membatalkan kolom lain yang memiliki ketergantungan fungsional pada kolom tersebut. Mungkin seharusnya, tetapi MySQL saat ini tidak benar-benar memahami semua hal tentang dependensi fungsional.

Jadi jika Anda memilih c.printable_name itu akan menunjukkan kepada Anda nilai nama negara mana yang dipilih secara acak, dan jika Anda memilih c.country_id itu akan menunjukkan kepada Anda ID negara mana yang dipilih secara acak — meskipun c.country_id adalah kriteria bergabung, jadi harus sama dengan r.country, yaitu NULL!

Apa yang dapat Anda lakukan untuk mengatasi masalah tersebut adalah:

  • kelompokkan dengan printable_name sebagai gantinya; harus OK jika printable_names unik, atau
  • pilih “r.country” serta printable_name, dan periksa apakah NULL, atau
  • lupa DENGAN ROLLUP dan lakukan kueri terpisah untuk jumlah akhir. Ini akan sedikit lebih lambat tetapi juga akan sesuai dengan ANSI SQL-92 sehingga aplikasi Anda dapat bekerja di database lain.

(*:MySQL memiliki opsi SQL_MODE ONLY_FULL_GROUP_BY yang seharusnya mengatasi masalah ini, tetapi itu terlalu jauh dan hanya memungkinkan Anda memilih kolom dari GROUP BY, bukan kolom yang memiliki ketergantungan fungsional pada GROUP BY. Jadi itu akan membuat kueri yang valid juga gagal, sehingga umumnya tidak berguna.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql dengan nilai yang dipisahkan koma

  2. Hibernate tidak menghormati bidang kunci utama MySQL auto_increment

  3. Doctrine2 - Beberapa sisipan dalam satu kesempatan

  4. Menggunakan Order By di codeigniter

  5. kesalahan sintaks:'pembatas' bukan input yang valid di sini