在查询考试70-461的MS SQL Server 2012(培训套件)一书中,它说明了逻辑处理中查询的GROUP BY
阶段:
此查询的最终结果有一行代表每个组 (除非过滤掉)。因此,所有阶段的表达都需要 在当前分组阶段之后的位置有些限制。所有 在后续阶段处理的表达式必须保证单个 每组价值。如果引用GROUP BY列表中的元素 (例如,国家),你已经有了这样的保证,所以这样的 允许引用。但是,如果要引用该元素 不属于GROUP BY列表(例如,empid),它必须是 包含在MAX或SUM等聚合函数中。那是因为 在单个组中的元素中可以有多个值,并且 保证只返回一个的唯一方法是 聚合价值观。
然后,作者提到HAVING
步骤,他使用COUNT(*) > 1
。我的问题是,如果GROUP BY
每组只有1行的结果,HAVING
阶段如何使用该单组行过滤掉任何超过1行的组...还有一半留在了吗?所以我在这里遗漏了一些东西。是否有某种隐藏的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;
请启发。
答案 0 :(得分: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
正如你所看到的,(Col1,Col2)有三个不同的元组 - (a,a),(a,b),(a,c),因此如果你是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) - 所以每个都有两个输入行,这就是{{1}是指,而不是结果集中的行数。
任何聚合函数(在有或在选择中)都与GROUP BY一起同时计算,而不是在它们各自的部分(HAVING,SELECT)。它们是相同的操作,这是它在选择或使用之前保持对组中行数的了解的方式。
Stackoverflow上的There is very good answer解释了聚合如何在幕后工作以便进一步阅读,所以我在此不再重复。