Tsql 使用派生表和CTE显示详细信息?

Tsql 使用派生表和CTE显示详细信息?,tsql,sql-server-2012,Tsql,Sql Server 2012,我在自学T-SQL,并努力理解以下示例 假设要显示几个未聚合的列以及 某些聚合表达式应用于整个结果集或 更大的分组级别。例如,您可能需要显示多个 Sales.SalesOrderHeader表中的列,并计算 每笔销售的到期总金额与所有销售的到期总金额的百分比 客户的销售。如果按CustomerID分组,则不能包括 Sales.SalesOrderHeader中的其他未聚合列,除非 按这些列分组。要解决这个问题,可以使用派生的 表或CTE 这里有两个例子 SELECT c.CustomerID,

我在自学T-SQL,并努力理解以下示例

假设要显示几个未聚合的列以及 某些聚合表达式应用于整个结果集或 更大的分组级别。例如,您可能需要显示多个 Sales.SalesOrderHeader表中的列,并计算 每笔销售的到期总金额与所有销售的到期总金额的百分比 客户的销售。如果按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

我希望有人以另一种方式解释上述示例,或以逻辑方式逐步解释,以便我了解它们是如何工作的?

此语句中的聚合(即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。总的来说,您可能会得到不同的结果,但由于您也在按SalesOrderID进行分组(我认为它在SalesOrderHeader表中是唯一的),因此每个组只有一条记录,因此这始终等于TotalDue值

在CTE示例中,您仅按CustomerId进行分组;由于客户可能有许多与之关联的销售订单,因此这些合计值将不同于TotalDue

编辑

通过以下方式解释分组中包含的字段的集合:

当按值分组时,具有相同值的所有行将被收集在一起,并对它们执行聚合函数。假设您有5行,总到期日为1,3行,总到期日为2,您将得到两条结果行;一个带1,一个带2。现在,如果你对这些进行求和,你有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

可运行示例:

如果这看起来很明显,我很抱歉,但我仍然不明白为什么TotalDue分组会使AvgOfTotalDue与TotalDue相同?请参阅sql FIDLE上的编辑/示例-希望这会让它更清晰一些。我仍然不太明白(我想我只需要做更多的例子。无论如何,我会给你最好的答案来帮助我。谢谢你的尝试。谢谢@DavidFolksman。我会尝试给出一个更清楚的解释/当我想到一些东西时会发布。同时,我建议玩一些查询,看看群组by是如何影响聚合值的;看看a。)t输出,并试图理解为什么他们是他们-一旦你这样做了几次,你应该开始了解背景中发生了什么。谢谢你坚持我的意见。在你的答案被否决后,否决我的问题有点小。