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

Почему в SQL Server я не могу этого сделать:

select  sum(count(id)) as 'count'
from    table

Но я могу сделать

select sum(x.count)
from
(
    select  count(id) as 'count'
    from    table   
) x

Разве это не одно и то же? Как я должен думать об этом, чтобы понять, почему первый блок кода не разрешен?


person Michael A    schedule 25.05.2012    source источник
comment
Первый способ тоже должен работать. Какую ошибку вы получаете?   -  person Sergey Kalinichenko    schedule 25.05.2012
comment
@Michael поделится ошибкой, которую вы получаете при запуске первого sql. Он должен работать нормально.   -  person Rakesh Juyal    schedule 25.05.2012
comment
Скалярное агрегирование (№ GROUP BY) всегда возвращает ровно одну строку. При каких обстоятельствах имеет смысл применить агрегирование к этой строке? Векторный агрегат возвращает одну строку для каждой группы. Хотя иногда может быть полезно применить другое агрегирование к результату, вам понадобится другое GROUP BY, примененное к двум агрегатам, чтобы это было полезно.   -  person Martin Smith    schedule 26.05.2012
comment
Стандарт SQL-92 явно запрещает вложенные агрегаты <value expression>, просто содержащийся в <set function specification>, не должен содержать <set function specification> или <subquery>   -  person Martin Smith    schedule 28.05.2012
comment
Проще говоря, aggregate(aggregate(...)) невозможно, потому что нет возможности указать GROUP BY ... OVER (GROUP BY ...). Т.е. если мы хотим вкладывать агрегаты, мы также должны иметь возможность вкладывать GROUP BY, что нам не разрешено (пока?). Вы говорите, что в ваших примерах нет GROUP BY? Но есть, а именно GROUP BY (), что всегда подразумевается, если не указано явно.   -  person Andriy M    schedule 30.05.2012
comment
Почему я получаю сообщение об ошибке, если я делаю только - (выберите count (id) как «count» из таблицы) x?   -  person david blaine    schedule 11.04.2013


Ответы (7)


SUM () в вашем примере не работает - SUM () из COUNT () означает то же самое, что и просто COUNT (). Таким образом, ни один из ваших примеров запросов, похоже, не дает ничего полезного.

Мне кажется, что вложение агрегатов будет иметь смысл только в том случае, если вы захотите применить два разных агрегирования, то есть GROUP BY для разных наборов столбцов. Чтобы указать две разные агрегации, вам нужно будет использовать функцию GROUPING SETS или функцию SUM () OVER. Может быть, если вы объясните, чего хотите достичь, кто-то покажет вам, как это сделать.

person nvogel    schedule 25.05.2012
comment
Мне более любопытно, почему я должен использовать производную таблицу для этого - почему SQL Server не поддерживает мой первый пример, но поддерживает второй? Мне они кажутся по сути одинаковыми. Никакой реальной цели, просить образования ради. - person Michael A; 28.05.2012
comment
Код @Michael SQL не позволяет использовать SUM () с агрегатными функциями. Если не позволяет, использовать нельзя: P - person aF.; 28.05.2012
comment
@Michael, потому что не было бы возможности в одном операторе SELECT указать разные агрегации для вложенных функций и не было бы смысла, если бы обе функции использовали одну и ту же агрегацию. Это ответ на вопрос? - person nvogel; 28.05.2012

Суть проблемы в том, что не существует такого понятия, как агрегирование агрегата, применяемого к отношению, см. Агрегация. Наличие такой концепции оставило бы слишком много дыр в определении и сделало бы предложение GROUP BY невозможным для выражения: ему необходимо определить как внутреннее агрегатное предложение GROUP BY , так и внешнее агрегатное выражение! Это относится также к другим совокупным атрибутам, таким как предложение HAVING.

Однако результатом применения агрегата к отношению является другое отношение, и это отношение результата, в свою очередь, может поддерживать новый оператор агрегирования. Это объясняет, почему вы можете объединить результат во внешний SELECT. Это не оставляет двусмысленности в определении, каждый SELECT имеет свои собственные отдельные предложения GROUP BY / HAVING.

person Remus Rusanu    schedule 28.05.2012

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

Обратите внимание, что в большинстве случаев нет смысла применять функцию агрегирования к результату другой функции агрегирования: в вашем примере sum(count(id)) == count(id).

person Gerardo Lima    schedule 29.05.2012

я хотел бы знать, каков ваш ожидаемый результат в этом sql

select  sum(count(id)) as 'count'
from    table

когда вы используете функцию count, будет возвращен только 1 результат (общее количество). Итак, могу ли я спросить, почему вы хотите суммировать единственный результат?

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

person AKZap    schedule 29.05.2012

У меня он работает с использованием SQLFiddle, не знаю, почему это не сработает для вас. Но у меня есть объяснение, почему это может не сработать для вас и почему альтернатива сработает ...

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

РЕДАКТИРОВАТЬ: в ответ на ваше редактирование / комментарий. Нет, эти два понятия не эквивалентны. РЕЗУЛЬТАТ будет эквивалентным, но процесс получения этого результата совсем не похож. Чтобы первый сработал, синтаксическому анализатору нужно выполнить некоторую работу, которая просто не имеет смысла для него (применение агрегата к одному значению, либо построчно, либо как), во втором случае агрегат наносится на стол. Тот факт, что таблица является временной виртуальной таблицей, не будет иметь значения для агрегатной функции.

person jmoreno    schedule 25.05.2012
comment
Извините, похоже, я ошибся в исходном (первом) запросе. Теперь исправил! - person Michael A; 25.05.2012

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

person user2908745    schedule 28.02.2014

Microsoft SQL Server его не поддерживает.

Вы можете обойти эту проблему, используя Derived таблицу:

select sum(x.count)
from
(
    select  count(id) as 'count'
    from    table   
) x

С другой стороны, использование приведенного ниже кода даст вам сообщение об ошибке.

select  sum(count(id)) as 'count'
from    table

Невозможно выполнить агрегатную функцию для выражения, содержащего агрегат или подзапрос

person Nilish    schedule 26.05.2012
comment
Это просто повторяет вопрос. - person Martin Smith; 26.05.2012
comment
@MartinSmith Нет, это факт, что проблема может быть решена с помощью производной таблицы. - person Nilish; 26.05.2012
comment
Факт, о котором уже говорилось в вопросе. Второй пример показывает, что производная таблица работает. Вопрос в том, почему так. - person Martin Smith; 26.05.2012
comment
@PankajGarg Мартин прав. Я знаю, что это невозможно, я хочу знать, почему. Вы просто переформулировали мой вопрос по-другому (на самом деле, совсем не по-другому) и сформулировали его как ответ. Это не один. - person Michael A; 28.05.2012