Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL:Общо ГРУПИРАНЕ С РЪКОВОДНО любопитство

Тъй като не избирате елемента, по който ГРУПИРАТЕ. Ако казахте:

GROUP BY c.printable_name

Ще получите очакваното NULL. Въпреки това вие групирате по друга колона, така че MySQL не знае, че printable_name участва в сборна група, и избира всяка стара стойност от тази колона, в обединяването на всички регистрации. (Така че е възможно да видите други страни освен Узбекистан.)

Това е част от по-широк проблем с MySQL, който разрешава какво можете да ИЗБЕРЕТЕ в заявка GROUP BY. Например, можете да кажете:

SELECT gender FROM registrations GROUP BY country;

и MySQL с радост ще избере една от стойностите за пол за регистрация от всяка държава, въпреки че няма пряка причинно-следствена връзка (известна още като „функционална зависимост“) между държава и пол. Други СУБД ще откажат горната команда на основание, че не е гарантирано, че има един пол на държава.(*)

Сега, това:

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

е ОК, защото има функционална зависимост между r.country и c.printable_name (ако приемем, че сте описали правилно своя country_id като ПРАВИЛЕН КЛЮЧ).

Въпреки това разширението WITH ROLLUP на MySQL е малко хак в начина, по който работи. На етапа на сборния ред в края той преминава през целия набор от резултати за предварително групиране, за да вземе стойностите му, и след това задава колоната група по NULL. Не нулира и други колони, които имат функционална зависимост от тази колона. Вероятно би трябвало, но MySQL в момента наистина не разбира цялата работа за функционалните зависимости.

Така че, ако изберете c.printable_name, той ще ви покаже коя стойност на името на държавата е избрана произволно, а ако изберете c.country_id, ще ви покаже коя държава е избрал произволно — въпреки че c.country_id е критерият за присъединяване, така трябва да бъде същото като r.country, което е NULL!

Това, което можете да направите, за да заобиколите проблема е:

  • вместо това групирайте по име за печат; трябва да е наред, ако printable_names са уникални, или
  • изберете „r.country“, както и printable_name и проверете дали е NULL, или
  • забравете WITH ROLLUP и направете отделна заявка за крайната сума. Това ще бъде малко по-бавно, но също така ще бъде съвместимо с ANSI SQL-92, така че приложението ви да може да работи с други бази данни.

(*:MySQL има опция SQL_MODE ONLY_FULL_GROUP_BY което би трябвало да реши този проблем, но отива твърде далеч и ви позволява да избирате само колони от GROUP BY, а не колони, които имат функционална зависимост от GROUP BY. Така че валидните заявки също ще се провалят, което го прави като цяло безполезно.)



  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 Workbench на Windows

  2. Бройте от таблица, но спрете да броите на определено число

  3. java.net.SocketException:Счупена тръба

  4. Как да разположите Percona Server за MySQL за висока наличност

  5. Функция MySQL DEGREES() – Преобразуване от радиани в градуси