Почему MySQL разрешает запросы «group by» без агрегатных функций?

Сюрприз – это абсолютно корректный запрос в MySQL:

select X, Y from someTable group by X 

Если вы попробовали этот запрос в Oracle или SQL Server, вы получите естественное сообщение об ошибке:

 Column 'Y' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

Итак, как MySQL определяет, какой Y будет отображаться для каждого X? Он просто выбирает один. Из того, что я могу сказать, он просто выбирает первый, который он находит. Обоснование заключается в том, что если Y не является ни агрегатной функцией, ни в предложении group by, то указание «выбрать Y» в вашем запросе не имеет смысла начинать. Поэтому я, как механизм базы данных, возвращу все, что захочу, и вам понравится.

Даже параметр конфигурации MySQL отключает эту «слабость». http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by

В этой статье даже упоминается, как MySQL подвергся критике за то, что ANSI-SQL не соблюдает в этом отношении. http://www.oreillynet.com/databases/blog/2007/05/debunking_group_by_myths.html

Мой вопрос: почему MySQL был разработан таким образом? Каково было их обоснование для взлома с ANSI-SQL?

Я считаю, что он должен был обрабатывать случай, когда группировка по одному полю будет означать, что другие поля также группируются:

 SELECT user.id, user.name, COUNT(post.*) AS posts FROM user LEFT OUTER JOIN post ON post.owner_id=user.id GROUP BY user.id 

В этом случае user.name всегда будет уникальным для user.id, поэтому есть удобство в том, чтобы не требовать имя user.name в предложении GROUP BY (хотя, как вы говорите, есть определенные возможности для проблем)

Согласно этой странице (онлайн-руководство 5.0), это обеспечивает лучшую производительность и удобство для пользователя.

К сожалению, почти все варианты SQL имеют ситуации, когда они нарушают ANSI и имеют непредсказуемые результаты.

Это звучит для меня так, как будто они предполагали, что к нему относятся как к функции «FIRST (Y)», которую имеют многие другие системы.

Скорее всего, эта конструкция – это то, о чем жалуется команда MySQL, но не хочет останавливаться на ней из-за количества приложений, которые могли бы сломаться.

обкрадывать

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

Кроме того, хорошая информация в этой теме .

Из того, что я прочитал на странице ссылок mysql, он говорит: «Вы можете использовать эту функцию для повышения производительности, избегая ненужной сортировки и группировки столбцов. Однако это полезно, прежде всего, когда все значения в каждом неагрегированном столбце, не названном в GROUP BY одинаковы для каждой группы ».

Я предлагаю вам прочитать эту страницу (ссылка на справочное руководство по mysql): http://dev.mysql.com/doc/refman/5.5/en//group-by-extensions.html

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

таблицы

 USER user_id | name USER_LOGIN_HISTORY user_id | date_logged_in 

USER_LOGIN_HISTORY имеет несколько строк для одного пользователя, поэтому, если я присоединился к пользователям, он вернет много строк. поскольку меня интересует только последняя запись, я бы сделал это

 select user_id, name, date_logged_in from( select u.user_id, u.name, ulh.date_logged_in from users as u join user_login_history as ulh on u.user_id = ulh.user_id where u.user_id = 1234 order by ulh.date_logged_in desc )as table1 group by user_id 

Это вернет одну строку с именем пользователя и в последний раз, когда пользователь войдет в систему.