Поведение MySQL GROUP BY - PullRequest
       19

Поведение MySQL GROUP BY

15 голосов
/ 29 октября 2009

Учитывая следующую таблицу 'foo'

ID | First Name | Last Name
----------------------------
67   John        Smith
----------------------------
67   Bill        Jacobs

Что first_name и last_name вернет следующий запрос и почему?

SELECT * FROM foo WHERE ID = 67 GROUP BY ID

Ответы [ 6 ]

27 голосов
/ 29 октября 2009

MySQL выбирает строку произвольно. На практике обычно используемые механизмы хранения MySQL возвращают значения из первой строки в группе относительно физического хранилища.

create table foo (id serial primary key, category varchar(10));

insert into foo (category) values 
  ('foo'), ('foo'), ('foo'), ('bar'), ('bar'), ('bar');

select * from foo group by category;

+----+----------+
| id | category |
+----+----------+
|  4 | bar      |
|  1 | foo      |
+----+----------+

Другие люди правы, что MySQL позволяет вам выполнять этот запрос, даже если он имеет произвольные и потенциально вводящие в заблуждение результаты. Стандарт SQL и большинство других поставщиков RDBMS запрещают этот неоднозначный запрос GROUP BY. Это называется Правило с одним значением : все столбцы в списке выбора должны быть явным образом частью критериев GROUP BY или же внутри агрегатной функции, например, COUNT(), MAX() и т. Д.

MySQL поддерживает режим SQL ONLY_FULL_GROUP_BY, который заставляет MySQL возвращать ошибку, если вы пытаетесь выполнить запрос, который нарушает стандартную семантику SQL.

AFAIK, SQLite - единственная другая СУБД, которая допускает неоднозначные столбцы в сгруппированном запросе. SQLite возвращает значения из последней строки в группе:

select * from foo group by category;

6|bar
3|foo

Мы можем представить запросы, которые не будут неоднозначными, но все же нарушают стандартную семантику SQL.

SELECT foo.*, parent_of_foo.* 
FROM foo JOIN parent_of_foo 
  ON (foo.parent_id = parent_of_foo.parent_id) 
GROUP BY foo_id;

Нет логичного способа, которым это могло бы привести к неоднозначным результатам. Каждая строка в foo получает свою собственную группу, если мы GROUP BY по первичному ключу foo. Таким образом, любой столбец из foo может иметь только одно значение в группе. Даже присоединение к другой таблице, на которую ссылается внешний ключ в foo, может иметь только одно значение на группу, если группы определены первичным ключом foo.

MySQL и SQLite доверяют вам создавать логически однозначные запросы. Формально каждый столбец в списке выбора должен быть функциональной зависимостью столбцов в критериях GROUP BY. Если вы не придерживаетесь этого, это ваша вина. : -)

Стандартный SQL является более строгим и запрещает некоторые запросы, которые могли бы быть однозначными - возможно, потому что это было бы слишком сложно для СУБД, чтобы быть уверенным в целом.

4 голосов
/ 29 октября 2009

Группировка MySQLs не соответствует стандартному поведению SQL, MySQL упрощает получение других столбцов, НО в то же время вы не можете быть уверены, какой из них получите.

Обновление: обратитесь к этой странице: http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html

При использовании этой функции все строки в каждая группа должна иметь одинаковые значения для столбцов, которые опущены из GROUP BY часть. Сервер бесплатный вернуть любое значение из группы, так результаты являются неопределенными, если все значения одинаковы.

3 голосов
/ 29 октября 2009

Не определено, какой результат вы собираетесь получить.

Мне всегда было интересно, почему такое поведение было даже разрешено. На самом деле, я хотел бы, чтобы такой код просто генерировал ошибку (предпочтительно, дешифруемую, ни в одном из ваших обычных MySQL «у вас нет проблем, но я не знаю, где»).

0 голосов
/ 29 октября 2009

MySQLs group by не соответствует стандартному поведению SQL, MySQL позволяет легко получить другие столбцы НО одновременно никогда не можешь быть уверен, какой из них ты получишь.

True. На самом деле это больше соответствует режиму SELECT DISTINCT ON, например, в postgres, за исключением того, что это позволяет вам указать порядок строк до расслоения (?) И, следовательно, какую строку вы получите (т. Е. Самую последнюю, самую старую и т.д.) *

Примечание. MySQL в режиме sql-совместимости будет отклонять GROUP BY с неопределенными столбцами, как в вашем примере.

0 голосов
/ 29 октября 2009

В стандартном SQL этот SQL должен завершиться с ошибкой процессора сервера, что-то вроде

"имя и фамилия не могут быть включены в предложение select, если только они не находятся в группе By или не входят в составную функцию."

MySql действительно возвращает данные для этого?

0 голосов
/ 29 октября 2009

Вполне вероятно, что будут выбраны имя и фамилия второй (последней) строки.

Вы можете добавить предложение ORDER BY, чтобы дать подсказки о том, как вы хотите отсортировать сгруппированные строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...