Почему MySQL разрешает запросы «group by» БЕЗ агрегатных функций? - PullRequest
56 голосов
/ 04 августа 2009

Сюрприз - это совершенно правильный запрос в 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, который он находит. Смысл в том, что если Y не является ни агрегатной функцией, ни предложением group by, то указание «select 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?

Ответы [ 6 ]

23 голосов
/ 11 августа 2011

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

19 голосов
/ 04 августа 2009

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

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 (хотя, как вы говорите, для проблем есть определенная область)

2 голосов
/ 04 августа 2009

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

Звучит так, будто они намеревались рассматривать его как функцию "FIRST (Y)", которую имеют многие другие системы.

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

Rob

1 голос
/ 04 января 2012

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

Также, хорошая информация в этой теме .

0 голосов
/ 16 февраля 2013

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

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

0 голосов
/ 25 августа 2012

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

Таблица

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

Возвращается одна строка с именем пользователя и последним входом пользователя в систему.

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