Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySQL:Total GROUP BY Z ROLLUP ciekawostką

Ponieważ nie wybierasz elementu, który grupujesz według. Jeśli powiedziałeś:

GROUP BY c.printable_name

Otrzymasz oczekiwany NULL. Jednak grupujesz według innej kolumny, więc MySQL nie wie, że printable_name bierze udział w grupie zbiorczej i wybiera każdą starą wartość z tej kolumny w połączeniu all rejestracje. (Więc możliwe jest, że zobaczysz inne kraje niż Uzbekistan.)

Jest to część szerszego problemu, w którym MySQL pozwala na to, co można wybrać w zapytaniu GROUP BY. Na przykład możesz powiedzieć:

SELECT gender FROM registrations GROUP BY country;

a MySQL z radością wybierze jedną z wartości płci do rejestracji z każdego kraju, mimo że nie ma bezpośredniego związku przyczynowego (czyli „zależności funkcjonalnej”) między krajem a płcią. Inne DBMS odrzucą powyższe polecenie na tej podstawie, że nie ma gwarancji, że w każdym kraju jest jedna płeć.(*)

Teraz to:

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

jest OK, ponieważ istnieje funkcjonalna zależność między r.country i c.printable_name (zakładając, że poprawnie opisałeś swój identyfikator kraju jako KLUCZ PODSTAWOWY).

Jednak rozszerzenie MySQL WITH ROLLUP jest trochę hackowe w sposobie, w jaki działa. Na końcu wiersza zestawienia przechodzi przez cały zestaw wyników grupowania wstępnego, aby pobrać jego wartości, a następnie następnie ustawia kolumnę grupowania według wartości NULL. Nie unieważnia również innych kolumn, które mają funkcjonalną zależność od tej kolumny. Prawdopodobnie powinno, ale MySQL obecnie tak naprawdę nie rozumie wszystkich zależności funkcjonalnych.

Tak więc jeśli wybierzesz c.printable_name, pokaże Ci się nazwa kraju, którą wybrała losowo, a jeśli wybierzesz c.country_id, pokaże Ci dowolny identyfikator kraju, który został wybrany losowo —  mimo że c.country_id jest kryterium przyłączenia, więc musi być to samo co r.country, czyli NULL!

Aby obejść ten problem, możesz:

  • pogrupuj według printable_name; powinno być OK, jeśli printable_names są unikalne, lub
  • wybierz „r.country” oraz printable_name i sprawdź, czy jest NULL, lub
  • zapomnij Z ROLLUP i wykonaj oddzielne zapytanie o sumę końcową. Będzie to trochę wolniejsze, ale będzie również zgodne z ANSI SQL-92, więc Twoja aplikacja będzie mogła działać na innych bazach danych.

(*:MySQL ma opcję SQL_MODE ONLY_FULL_GROUP_BY to ma rozwiązać ten problem, ale idzie o wiele za daleko i pozwala tylko wybrać kolumny z GROUP BY, a nie kolumny, które mają funkcjonalną zależność od GROUP BY. Więc spowoduje to, że prawidłowe zapytania również zakończą się niepowodzeniem, przez co będą generalnie bezużyteczne.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Łączenie w łańcuchy orX w konstruktorze zapytań Doctrine2

  2. post zmieniono nazwę pliku z przesyłania do bazy danych

  3. Uzyskaj wyniki z mysql na podstawie szerokości geograficznej i długości geograficznej

  4. Jak efektywnie korzystać z MySQLDB SScursor?

  5. kategoria php, drzewo podkategorii