首页 > 解决方案 > 在 CTE 中使用 GROUP BY 进行聚合

问题描述

我正在使用 TSQL 和 AdventureWorks 2014 来尝试计算由 SalesOrderID 指定的每个唯一订单的所有 LineTotals 的总和。我加入了 SalesOrderHead.SalesOrderID,因为在 SalesOrderHeader 中,SalesOrderID 是主键。当每个 SalesOrderID 只返回一条记录时,此查询将永远运行,并返回重复的 SalesOrderID。希望这是有道理的...

我要做的是计算 SumPerOrderCTE 中按 SalesOrderID 分组的 SUM(LineTotal),然后将其连接到 SalesOrderHeader 以选择一些额外的表,并且只从 SumPerOrder 中选择具有与 SalesOrderID 匹配的 SalesOrderHeader 的记录。

有什么建议么?我似乎无法弄清楚为什么它没有做它应该做的事情..

这是输出(请注意 SalesOrderID 都是相同的,差异应该大部分是 0 但不是): buggy_output

输出的一般外观的小样本: desired_output

CREATE OR ALTER PROC [dbo].[SalesOrderDataReviewCTE]
AS
WITH SumPerOrder (SalesOrderID, CalculatedSubTotalFromDetail)
AS
(
SELECT
    SalesOrderID
    ,SUM(LineTotal)
FROM AdventureWorks2014.Sales.SalesOrderDetail
GROUP BY SalesOrderID
)
SELECT
    soh.SalesOrderID
    ,soh.SalesOrderNumber
    ,soh.SubTotal AS OriginalSubTotal
    ,spo.CalculatedSubTotalFromDetail
    ,(soh.SubTotal - spo.CalculatedSubTotalFromDetail) AS Difference
FROM AdventureWorks2014.Sales.SalesOrderHeader soh
    INNER JOIN SumPerOrder spo
        ON soh.SalesOrderID = spo.SalesOrderID

标签: sqlsql-servertsql

解决方案


为什么要使用 CTE?

CTE 只是一种使用可重复代码创建临时表的方便且单次查询的方法。执行此操作时,该SumPerOrder表缺少SalesOrderDetail. 因此,与 with 的连接比 with的SalesOrderHeader直接连接花费的时间要长得多。SalesOrderHeaderSalesOrderDetail

更简单的方法是:

SELECT
    soh.SalesOrderID
    ,soh.SalesOrderNumber
    ,soh.SubTotal AS OriginalSubTotal
    ,spo.SUM(LineTotal) as CalculatedSubTotalFromDetail
    ,(soh.SubTotal - spo.SUM(LineTotal)) AS Difference
FROM AdventureWorks2014.Sales.SalesOrderHeader soh
    INNER JOIN AdventureWorks2014.Sales.SalesOrderDetail spo
        ON soh.SalesOrderID = spo.SalesOrderID
GROUP BY spo.SalesOrderID,soh.SalesOrderNumber,soh.SubTotal

推荐阅读