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

Учитывая следующую таблицу '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

Ответы

Ответ 1

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 является более строгим и запрещает некоторые запросы, которые могут быть однозначными - вероятно, потому, что это было бы слишком сложно для RDBMS, чтобы быть уверенным в целом.

Ответ 2

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

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

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

Ответ 3

Это undefined, результат которого вы получите.

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

Ответ 4

Скорее всего, будет выбрана первая и последняя фамилия и имя последней строки.

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

Ответ 5

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

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

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

Ответ 6

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

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

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