Является ли предложение GROUP BY в SQL избыточным? - PullRequest
12 голосов
/ 22 декабря 2010

Всякий раз, когда мы используем статистическую функцию в 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?

Ответы [ 4 ]

8 голосов
/ 22 декабря 2010

Всякий раз, когда мы используем статистическую функцию в 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
5 голосов
/ 22 декабря 2010

Я могу согласиться с тем, что вы говорите, но это не избыточно в во всех случаях.

Учтите это:

SELECT FirstName 
       + ' (' + REPLACE(Address1, ',', ' ') + ' '
       + REPLACE(Address2, ',', ' ') + ', '
       + UPPER(State) + ' '
       + 'USA)',
       COUNT(*)
FROM Profiles
GROUP BY FirstName, Address1, Address2, State

В данном случае мне просто нужно количество профилей с одинаковыми именами и адресами.
Как видите, мне не нужно было повторять «сложные» операции SELECT в операторе GROUP BY.

Я думаю, что, допустив это «иногда так, иногда так», вы облагаете налогом необходимость делать повторения большую часть времени.

1 голос
/ 22 декабря 2010

Предложение 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 поддерживает аналитику, но я не знаю подробностей.

0 голосов
/ 22 декабря 2010
  1. Основное здесь - (2 * (x + y)) / z + 1, MyFunction(x, y) после GROUP BY, необходимо, чтобы сумма знала, как суммировать.
  2. Но (2 * (x + y)) / z + 1, MyFunction(x, y) после SELECT необязательно.То, как вы хотите, чтобы результат стал, не влияет на sum()
    Так же, как сказал BeemerGuy, 2. не всегда совпадает с 1.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...