2016-05-06 3 views
0

Следующий запрос предназначен для того, чтобы вернуть имя ученика, название своей школы и название ее школьных округов, а также количество школ в ее округе. Делает ли GROUP BY d.id что-нибудь? Похоже, что COUNT() в инструкции SELECT волшебным образом делает то же самое. Если это не нужно, это хорошая практика?Требуется ли GROUP BY с помощью COUNT()?

SELECT s.name student_name, sc.name school_name, d.name district_name, 
COUNT(sc.id) school_count_at_students_district 
FROM students s 
INNER JOIN schools sc ON sc.id=s.schools_id 
LEFT OUTER JOIN schools sc2 ON sc2.districts_id=sc.districts_id 
INNER JOIN districts d ON d.id=sc.districts_id 
WHERE s.id=123; 
+1

Общее правило GROUP BY: «Если указано предложение GROUP BY, каждая ссылка столбца в списке SELECT должна либо идентифицировать столбец группировки, либо быть аргументом функции набора.«Если вы нарушите это правило, то более старые версии MySQL сделают что-то по-другому, несколько непредсказуемым образом. Новейшие версии MySQL, тем не менее, вызовут ошибку. – jarlh

+0

На самом деле это очень сложно ответить на все поддельные имена столбцов и не знать, что вы пытаетесь выполнить с вашим запросом – user2278120

+0

@jarlh А, так что с моими данными он может «генерировать» результаты, пока каждая запись содержит столбец группы? – user1032531

ответ

1

Допустим, вы имеете следующую таблицу:

+----+-----+-----------+ 
| f1 | f2 | f3  | 
+----+-----+-----------+ 
| 1 | 4.3 | apple  | 
| 2 | 1.4 | orange | 
| 2 | 3 | pear  | 
| 3 | 1.2 | kiwi  | 
| 3 | 2.2 | pineapple | 
| 3 | 1 | pineapple | 
+----+-----+-----------+ 

И вы исполняете:

SELECT f1, sum(f2), f3 FROM table GROUP BY f1, f3; 

Мы включают f1 и f3 столбцы в GROUP BY, чтобы сообщить MySQL, как агрегировать. Вы получите обратно:

+----+-----+-----------+ 
| f1 | f2 | f3  | 
+----+-----+-----------+ 
| 1 | 4.3 | apple  | 
| 2 | 1.4 | orange | 
| 2 | 3 | pear  | 
| 3 | 1.2 | kiwi  | 
| 3 | 3.3 | pineapple | 
+----+-----+-----------+ 

Здесь мы получаем различные группировки f1 и f3 записей, как мы ожидаем.

Если вы опускаете либо f1, либо f3 в GROUP BY, каждая РСУБД на планете собирается выбросить ошибку, кроме MySQL. Базы данных, отличные от MySQL, требуют, чтобы вы четко указывали, как вы суммируете свои поля, и они либо должны быть сгруппированы в GROUP BY, либо объединены с формулой в SELECT.

Если в MySQL, вы опускаете GROUP BY:

SELECT f1, sum(f2), f3 FROM table; 

вы получите записи назад, как:

+----+-----+-----------+ 
| f1 | f2 | f3  | 
+----+-----+-----------+ 
| 1 | 4.3 | apple  | 
| 2 | 4.4 | orange |  
| 3 | 4.5 | kiwi  |  
+----+-----+-----------+ 

, которые могут быть нонсенсом. Референциальная целостность ваших записей была скомпрометирована. Oranges не 4.4 и Kiwi не 4.5. То, что сделал MySQL, - это первое значение, которое оно встретило в таблице, и выплюнуть его. Такое поведение может иметь смысл, если:

  1. Вы не заботятся о том, какое значение MySQL выбирает из f3 или ...
  2. Вы полагаетесь на двигатель хранения MySQL, чтобы поддерживать порядок ваших записей, что, следовательно, делает вас дураком. Не делай этого.

Ваш лучший выбор для переносимости кода и неожиданных результатов будет включать GROUP BY если вы агрегирование с функцией в вашем SELECT. В противном случае вы получите то, что заслуживаете.

+0

Спасибо JNevill. По моим конкретным данным, я получал одинаковые результаты, которые меня смутили. Да, я использовал MySQL. С тех пор я добавил предложение GROUP BY. – user1032531

+0

'GROUP BY' - одна из тех странных вещей в СУБД. Вы могли бы подумать, что при отключении оператора GROUP BY, когда вы агрегируете поле в SELECT, СУБД просто предположил бы, что любые агрегированные поля без формулы будут в опущенном «GROUP BY». MySQL позволяет исключить «GROUP BY», но не делает этого предположения, вместо этого возвращает 'FIRST()' каждого опущенного поля и все другие ошибки СУБД. Лучше всего всегда быть максимально ясными в ваших операторах SQL, чтобы вы не столкнулись ни с одним из странных предположений, сделанных СУБД. – JNevill

1

MySQL не имеет отношения к предложению GROUP BY.

Но эта практика неверна, согласно определению ANSI SQL. Если вы думаете о переносе в другие СУБД, такие как Oracle, PostgresQL ... поместите предложение GROUP BY и его столбцы.

Кроме того, это легче понять, когда Tou положить его.

+0

Спасибо Пастор. Если я понимаю вас, это может быть абсолютно не обязательно для MySQL, но оно должно использоваться с другими базами данных и улучшать читаемость. – user1032531

+0

@ user1032531, а для более новых версий MySQL требуется предложение GROUP BY. (Возможно, есть режим обратной совместимости?) – jarlh