Является ли предложение GROUP BY в SQL избыточным?
Всякий раз, когда мы используем агрегатную функцию в SQL (MIN
, MAX
, AVG
и т.д.), мы должны всегда GROUP BY
все неагрегированные столбцы, например:
SELECT storeid, storename, SUM(revenue), COUNT(*)
FROM Sales
GROUP BY storeid, storename
Это становится еще более назойливым, когда мы используем функцию или другое вычисление в нашем операторе SELECT, так как это также должно быть скопировано в предложение GROUP BY.
SELECT (2 * (x + y)) / z + 1, MyFunction(x, y), SUM(z)
FROM AnotherTable
GROUP BY (2 * (x + y)) / z + 1, MyFunction(x, y)
Если мы когда-либо изменим инструкцию SELECT, мы должны помнить о том же изменении в нашем предложении GROUP BY.
Итак, предложение GROUP BY является избыточным?
- Если это действительно так, то почему вообще существует предложение GROUP BY в SQL?
- Если это не так, то какие дополнительные функции предоставляет GROUP BY?
Ответы
Ответ 1
Всякий раз, когда мы используем агрегатную функцию в SQL (MIN, MAX, AVG и т.д.), мы всегда должны GROUP BY всеми неагрегированными столбцами
Это вообще не так. MySQL, к примеру, не требует этого, и стандарт SQL также не говорит об этом.
Это становится еще более назойливым, когда мы используем функцию или другое вычисление в нашем операторе SELECT, так как это также должно быть скопировано в предложение GROUP BY.
Также не верно в целом. MySQL (и, возможно, другие базы данных тоже) позволяют использовать псевдонимы столбцов в предложении GROUP BY:
SELECT (2 * (x + y)) / z + 1 AS a, MyFunction(x, y) AS b, SUM(z)
FROM AnotherTable
GROUP BY a, b
Если это не так, то какие дополнительные функции предоставляет GROUP BY?
Единственный способ указать, что сгруппировать, - это использовать предложение GROUP BY. Вы не можете вывести его из столбцов, указанных в SELECT. На самом деле вам даже не нужно выбирать все столбцы, упомянутые в GROUP BY:
SELECT MAX(col2)
FROM foo
GROUP BY col1
HAVING COUNT(*) = 2
Ответ 2
Я могу согласиться с тем, что вы говорите, но это не избыточно в случаях all.
Рассмотрим это:
SELECT FirstName
+ ' (' + REPLACE(Address1, ',', ' ') + ' '
+ REPLACE(Address2, ',', ' ') + ', '
+ UPPER(State) + ' '
+ 'USA)',
COUNT(*)
FROM Profiles
GROUP BY FirstName, Address1, Address2, State
В этом случае я просто хочу, чтобы число однотипных имен, одинаковых адресов.
Как вы можете видеть, мне не пришлось повторять "сложные" операции SELECT
в инструкции GROUP BY
.
Я думаю, чтобы позволить "иногда так, иногда так", вам приходится делать повторения большую часть времени.
Ответ 3
Предложение GROUP BY
не является избыточным - его функция определяет область действия, на которой работают агрегатные функции. Это ваше убеждение в том, что оптимизатор должен читать из предложения SELECT, чтобы узнать, какова область действия группировки, но доступ к псевдонимам столбцов доступен в предложении ORDER BY
как можно раньше (за исключением MySQL, где GROUP BY
и HAVING
- вспомогательные псевдонимы столбцов). В настоящее время нет средств для поддержки ваших ожиданий. Стандарты ANSI хороши, но на самом деле стандарты ANSI не реализованы в целом поставщиками. Он поддерживает поиск и поддержку, как то, как PostgreSQL 8.4+ поддерживает больше аналитических функций, чем Oracle (конечно, больше, чем SQL Server).
Поддержка MySQL и SQLite, исключающая столбцы из GROUP BY
, но эти значения столбцов для документации произвольны - это значение не может быть гарантировано возвращено последовательно. И объем группировки также различен, что может существенно повлиять на возвращаемый результат. Тогда возникает проблема полагаться на специфический синтаксис поставщика, когда требуется перенос в другие базы данных, поскольку DB2, Oracle, SQL Server и PostgreSQL не поддерживают функциональность.
Но с появлением аналитической/оконной/ранговой функциональности вы можете получить совокупную функциональность без GROUP BY. IE:
SELECT t.id,
COUNT(t.column) OVER(PARTITION BY t.id) AS num,
SUM(t.column) OVER(PARTITION BY t.id) AS sum
FROM YOUR_TABLE t
Это более подробный и подверженный ошибкам, хотя из-за того, что вы не можете определить PARTITION BY
/ORDER BY
, который применяется ко всем аналитическим функциям в запросе. В настоящее время... Но Analytics не вытеснит агрегаты в ближайшее время - поддержка началась в Oracle 9i, SQL Server 2005+ и PostgreSQL 8.4+. Я знаю, что DB2 поддерживает аналитику, но я не знаю подробностей, кроме этого.
Ответ 4
- Главное здесь
(2 * (x + y)) / z + 1, MyFunction(x, y)
после GROUP BY
, нужно, чтобы сумма знала, как сводить.
- Но
(2 * (x + y)) / z + 1, MyFunction(x, y)
после SELECT
необязательно. Как вы хотите, чтобы результат стал, а не влиял на sum()
Как и сказал BeemerGuy, 2. не всегда одинаково с 1.