2013-11-08 3 views
2

В книге Запросы MS SQL Server 2012 (учебный комплект) для экзамена 70-461 это говорит о GROUP BY фаза запроса в логической обработки:Что возвращает фаза GROUP BY в обработке логических запросов в SQL?

Конечный результат этого запроса содержит одну строку, представляющую каждую группу (если не отфильтровано). Поэтому выражения во всех фазах, которые принимают место после текущей фазы группировки, несколько ограничены. Все выражения , обработанные на последующих этапах, должны гарантировать одно значение для каждой группы. Если вы ссылаетесь на элемент из списка GROUP BY (например, страны), у вас уже есть такая гарантия, поэтому такая ссылка разрешена. Однако, если вы хотите обратиться к элементу, который не является частью вашего списка GROUP BY (например, empid), он должен быть , содержащимся в совокупной функции, такой как MAX или SUM. Это связано с тем, что в элементе внутри одной группы возможны , а - единственный способ гарантировать, что только один будет возвращен, - суммировать значения.

Затем автор упоминает шаг HAVING, где использует COUNT(*) > 1. Мой вопрос: если GROUP BY имеет только результат из 1 строки на группу, как фаза HAVING использует эту одну группу, чтобы отфильтровывать любые группы с более чем одной строкой ... которые она делает, поскольку половина из них остается? Так что я что-то пропустил. Есть ли какая-то скрытая колонка COUNT, прикрепленная к каждой группе?

Этот запрос:

SELECT country, YEAR(hiredate) AS yearhired, COUNT(*) AS numemployees 
FROM HR.Employees 
WHERE hiredate >= '20030101' 
GROUP BY country, YEAR(hiredate) 
HAVING COUNT(*) > 1 
ORDER BY country , yearhired DESC; 

Пожалуйста englighten.

+0

Можете ли вы разместить запрос? –

+1

Счетчик (*) рассчитывается до фазы группировки. – Arvo

+1

@Arvo Рассчитывается в то же время, что и фаза группировки, она является частью одной и той же операции (агрегат Stream/hash) – GarethD

ответ

0

Если автор ссылается на одну строку на группу в GROUP BY, он ссылается на результирующий набор, то при обращении к строкам каждой группы в HAVING он ссылается на ввод.

себе это просто набор данных

Col1 Col2 Value 
---------------------- 
    a  a  1 
    a  b  1 
    a  b  1 
    a  b  2 
    a  c  1 
    a  c  5 

Как вы можете видеть, что есть 3 различных кортежей для (Col1, Col2) - (а, а), (а, Ь), (а, с) , поэтому, если вы GROUP BY Col1, Col2, вы получите три строки в своем результате (по одному на группу).

SELECT Col1, Col2 
FROM T 
GROUP BY Col1, Col2; 

дает

Col1 Col2  
------------- 
    a  a 
    a  b 
    a  c 

Это то, что автор имеет в виду, говоря «по одной строке для каждой группы».

Однако, расширяясь снова, вы можете видеть, что есть две строки с кортежем (a, b) и два для (a, c) - так что для каждого из них есть два входных строки, это то, что ссылается на COUNT(*) а не количество строк в результирующем наборе.

Любые агрегатные функции (либо в наличии, либо в выборе) рассчитываются одновременно как GROUP BY, а не в их соответствующих частях (HAVING, SELECT). Они - одна и та же операция, так как она поддерживает знание количества строк в группе до того, как они будут использоваться в выборе или наличии.

There is very good answer на Stackoverflow, объясняющий, как агрегаты работают за кулисами для дальнейшего чтения, поэтому я не буду повторять его здесь.

+0

Спасибо, что разобрался. – sprocket12