2009-08-03 2 views
49

Сюрприз - это вполне допустимый запрос в MySQL:Почему MySQL разрешает запросы «group by» без агрегатных функций?

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?

+0

Позвольте мне это так. Я рассматриваю этот вариант дизайна как эквивалент языка программирования, который позволяет разрешить и игнорировать, скажем, «нулевое» значение слева. например "null = 3". Просто нет причин позволять этому случиться. Это ошибка, которая всегда и опасно ошибочна. –

+3

@lumpynose, ерунда, это могло быть верно pre 5.x – Johan

+4

@lumpynose Можете ли вы дать ссылку на ваше утверждение? – Barranka

ответ

11

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

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, поэтому есть удобство в том, чтобы не требовать имя пользователя в предложении GROUP BY (хотя, как вы говорите, есть определенный объем проблем)

+1

Значит, это было просто сохранить некоторую типизацию (как при наборе текста на клавиатуре)? Хех. –

+2

Меньше столбцов в разделе GROUP BY означает более быстрое время выполнения, поэтому это оптимизирующий взлом. Я использую 'MAX (имя_пользователя) имя AS' в похожих запросах в реализациях ANSI SQL. – wqw

+0

@wqw: мусор. user.name находится либо в группе, либо в совокупности. В лучшем случае это двусмысленно. См. Комментарии к http://stackoverflow.com/questions/6060241/which-is-the-least-expensive-aggregate-function-in-the-absence-of-any/6060419#6060419 Только MySQL позволяет такие взломы, например http://stackoverflow.com/q/6642241/27535 – gbn

1

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

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

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

Роб

19

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

+0

+1 Прямая ссылка на ответ –

+0

+1, для ответа MySQL :). Я использую это все время, чтобы избежать выполнения подзапроса, который выполняет «ORDER BY ... LIMIT 1» ... вам просто нужно быть осторожным, зная, что данные, которые вы получаете в неагрегированных столбцах, будут случайными для все строки, соответствующие вашим условиям. –

+0

LInk мертв, можете ли вы его обновить? или лучше, но вставьте документы здесь, если он снова сломается – szx

1

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

Также, хорошая информация находится в this thread.

-1

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

Столы

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 

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

+0

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

+0

Этот надуманный пример длиннее и медленнее, чем просто прямое «max», и поэтому не поддерживает ваше утверждение о том, что это «очень полезный инструмент». Если вы не можете даже придумать пример полезности, я серьезно сомневаюсь в его полезности. Я также не считаю, что намеренное использование часто неопределенной функциональности будет более полезным * в * более сложных запросах. –

0

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

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

Смежные вопросы