Но почему я получаю Узбекистан на общую сумму ??
Потому что вы НЕ ВЫБИРАЕТЕ элемент, который вы группируете. Если бы вы сказали:
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 как ПЕРВИЧНЫЙ КЛЮЧ).
Однако расширение MySQL WITH ROLLUP - это своего рода хак в том, как оно работает. На этапе накопительной строки в конце он проходит по всему набору результатов предварительной группировки, чтобы получить его значения, а , а затем устанавливает для столбца группировки по значение NULL. Он также не обнуляет другие столбцы, которые имеют функциональную зависимость от этого столбца. Вероятно, так и должно быть, но MySQL в настоящее время не совсем понимает все о функциональных зависимостях.
Таким образом, если вы выберете c.printable_name, он покажет вам, какое значение названия страны было выбрано случайным образом, а если вы выберите c.country_id, он покажет вам любой идентификатор страны, который он выбрал случайным образом, даже если c.country_id является критерием объединения, поэтому должен быть таким же, как r.country, который равен NULL!
Что вы можете сделать, чтобы обойти эту проблему:
- группировать по printable_name вместо; должно быть в порядке, если printable_names уникальны, или
- выберите «r.country», а также printable_name и проверьте, что это NULL, или
- забудьте WITH ROLLUP и выполните отдельный запрос для конечной суммы. Это будет немного медленнее, но также будет совместимо с ANSI SQL-92, чтобы ваше приложение могло работать с другими базами данных.
(*: MySQL имеет параметр SQL_MODE ONLY_FULL_GROUP_BY , который должен решить эту проблему, но заходит слишком далеко и позволяет выбирать только столбцы из GROUP BY, а не столбцы с функциональной зависимостью на GROUP BY. Таким образом, это приведет к сбою действительных запросов, что сделает его вообще бесполезным.)