我正在教自己T-SQL,并且正在努力理解下面的例子。
假设您要显示几个非聚合列 一些适用于整个结果集或a的聚合表达式 更大的分组水平。例如,您可能需要显示几个 Sales.SalesOrderHeader表中的列并计算 与TotalDue相比,每次销售的TotalDue的百分比 客户的销售。如果按CustomerID分组,则不能包含 除非您,否则Sales.SalesOrderHeader中的其他非聚合列 按这些列分组。要解决这个问题,您可以使用派生 桌子或CTE。
以下是两个例子......
SELECT c.CustomerID, SalesOrderID, TotalDue, AvgOfTotalDue,
TotalDue/SumOfTotalDue * 100 AS SalePercent
FROM Sales.SalesOrderHeader AS soh
INNER JOIN
(SELECT CustomerID, SUM(TotalDue) AS SumOfTotalDue,
AVG(TotalDue) AS AvgOfTotalDue
FROM Sales.SalesOrderHeader
GROUP BY CustomerID) AS c ON soh.CustomerID = c.CustomerID
ORDER BY c.CustomerID;
WITH c AS
(SELECT CustomerID, SUM(TotalDue) AS SumOfTotalDue,
AVG(TotalDue) AS AvgOfTotalDue
FROM Sales.SalesOrderHeader
GROUP BY CustomerID)
SELECT c.CustomerID, SalesOrderID, TotalDue,AvgOfTotalDue,
TotalDue/SumOfTotalDue * 100 AS SalePercent
FROM Sales.SalesOrderHeader AS soh
INNER JOIN c ON soh.CustomerID = c.CustomerID
ORDER BY c.CustomerID;
为什么此查询不会产生相同的结果..
SELECT CustomerID, SalesOrderID, TotalDue, AVG(TotalDue) AS AvgOfTotalDue,
TotalDue/SUM(TotalDue) * 100 AS SalePercent
FROM Sales.SalesOrderHeader
GROUP BY CustomerID, SalesOrderID, TotalDue
ORDER BY CustomerID
我正在寻找某人以另一种方式解释上述例子,或者逻辑地逐步解释它,以便我能理解它们是如何工作的?
答案 0 :(得分:2)
此声明中的聚合(即SUM和AVG)不执行任何操作:
SELECT CustomerID, SalesOrderID, TotalDue, AVG(TotalDue) AS AvgOfTotalDue,
TotalDue/SUM(TotalDue) * 100 AS SalePercent
FROM Sales.SalesOrderHeader
GROUP BY CustomerID, SalesOrderID, TotalDue
ORDER BY CustomerID
原因是您要按TotalDue进行分组,因此同一组中的所有记录对此字段都具有相同的值。对于AVG,这意味着您必须保证AvgOfTotalDue始终等于TotalDue。对于SUM,你可能得到一个不同的结果,但是你也正在按SalesOrderID进行分组(我认为它在SalesOrderHeader表中是唯一的),你每组只有一条记录,所以这总是等于TotalDue值。
使用CTE示例,您只能按CustomerId进行分组;由于客户可能有许多与之关联的销售订单,因此这些汇总值将与TotalDue不同。
修改强>
分组中包含的字段汇总说明:
按值分组时,将同时收集具有相同值的所有行,并对它们执行聚合函数。假设您有5行,总计1和3,总共2,你得到两个结果行;一个是1s,一个是2s。现在,如果你对这些进行总和,你就有3 * 1和2 * 2。现在除以该结果行中的行数(得到平均值),你得到3 * 1/3和2 * 2/2;因此取消了1和2。
select totalDue, avg(totalDue)
from (
select 1 totalDue
union all select 1 totalDue
union all select 1 totalDue
union all select 2 totalDue
union all select 2 totalDue
) x
group by totalDue
select uniqueId, totalDue, avg(totalDue), sum(totalDue)
from (
select 1 uniqueId, 1 totalDue
union all select 2 uniqueId, 1 totalDue
union all select 3 uniqueId, 1 totalDue
union all select 4 uniqueId, 2 totalDue
union all select 5 uniqueId, 2 totalDue
) x
group by uniqueId