可以在一个交叉应用中使用两个聚合吗?
Posted
技术标签:
【中文标题】可以在一个交叉应用中使用两个聚合吗?【英文标题】:Two aggregates in one cross apply possible? 【发布时间】:2019-08-14 09:14:56 【问题描述】:我对 SQL 非常陌生,我正在尝试使用 CROSS APPLY,对此我知之甚少。
我正在尝试从两个不同的表中提取两个按 ID 排序的项目的总和。一个墨盒分配的所有项目的一个 SUM,一个重新填充到墨盒中的所有项目的一个 SUM。分配和补充在单独的表中。在示例 1 中,您可以看到一段适用于这两个 SUM 之一的代码,目前它适用于 Dispensed SUM,但如果我为重新填充的 SUM 更改所有内容,它也可以工作。关键是我只能在这个 CROSS APPLY 中做一个 SUM,不管两者中的哪一个。
所以当我尝试在这个 CROSS APPLY 中提取两个 SUM 时会出错,可能是因为我真的不知道自己在做什么。我尝试使用示例 2 中的代码(几乎是相同的代码)来执行此操作。
一些额外的上下文:
这里有两个重要的 ID:
CartridgeRefill.FK_CartridgeRegistration_Id
(或 ID)是磁带本身的 ID。 FK_CartridgeRefill_Id
是重新填充的 ID,一个墨盒可以经过多次重新填充,并且分配通过它们分配的重新填充来注册。这就是为什么您可以在输出中多次看到同一个 ID。
样本 1:
SELECT CartridgeRefill.FK_CartridgeRegistration_Id AS ID, Sums.Dispensed
FROM CartridgeRefillItem
CROSS APPLY (
SELECT SUM(CartridgeDispenseAttempt.Amount) AS Dispensed
FROM CartridgeDispenseAttempt
WHERE CartridgeRefillItem.FK_CartridgeRefill_Id = CartridgeDispenseAttempt.FK_CartridgeRefill_Id
) AS Sums
JOIN CartridgeRefill ON CartridgeRefillItem.FK_CartridgeRefill_Id = CartridgeRefill.FK_CartridgeRefill_Id
示例 2:
SELECT CartridgeRefill.FK_CartridgeRegistration_Id AS ID, Sums.Dispensed, Sums.Refilled
FROM CartridgeRefillItem
CROSS APPLY (
SELECT SUM(CartridgeDispenseAttempt.Amount) AS Dispensed
,SUM(CartridgeRefillItem.Amount) AS Refilled
FROM CartridgeDispenseAttempt
WHERE CartridgeRefillItem.FK_CartridgeRefill_Id = CartridgeDispenseAttempt.FK_CartridgeRefill_Id
) AS Sums
JOIN CartridgeRefill ON CartridgeRefillItem.FK_CartridgeRefill_Id = CartridgeRefill.FK_CartridgeRefill_Id
当我运行示例 1 时,我得到以下输出:
ID Dispensed
10 95
8 143
6 143
11 70
11 312
11 354
8 19
8 24
8 3
8 33
这个输出是正确的,它在它所属的ID旁边显示分配的物品数量。
这是我在运行示例 2 时遇到的错误:
Msg 4101, Level 15, State 1, Line 15
Aggregates on the right side of an APPLY cannot reference columns from the left side.
但我想看到的是:
ID Dispensed Refilled (example)
10 95 143
8 143 12
6 143 etc...
11 70
11 312
11 354
8 19
8 24
8 3
8 33
我认为这与 CROSS APPLY 逐行运行有关吗?但同样,我仍然不完全知道我在做什么。任何帮助将不胜感激,请询问您需要知道的任何内容:)
【问题讨论】:
您正在使用哪个数据库。最好的选择是您可以添加一些示例数据和预期的输出。 【参考方案1】:错误是不言自明的,您不能使用CROSS APPLY
之外的引用运行聚合。您需要通过添加额外的子查询来计算SUM
或使用GROUP BY
子句来重写您的查询。我很快就把这个刮掉了:
SELECT CartridgeRefill.FK_CartridgeRegistration_Id AS ID, Sums.Dispensed, SUM(CartridgeRefillMedication.Amount) AS Refilled
FROM CartridgeRefillItem
CROSS APPLY (
SELECT SUM(CartridgeDispenseAttempt.Amount) AS Dispensed
FROM CartridgeDispenseAttempt
WHERE CartridgeRefillItem.FK_CartridgeRefill_Id = CartridgeDispenseAttempt.FK_CartridgeRefill_Id
) AS Sums
JOIN CartridgeRefill ON CartridgeRefillMedication.FK_CartridgeRefill_Id = CartridgeRefill.FK_CartridgeRefill_Id
GROUP BY CartridgeRefill.FK_CartridgeRegistration_Id;
希望这行得通。
【讨论】:
您好,Evaldas,感谢您的回复 :) 我在代码中关于表格名称的一些错误,现在已更正。但是我运行了你的代码,我得到了这个错误:Msg 8120, Level 16, State 1, Line 33 列 'Sums.Dispensed' 在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。 尝试用SUM(Sums.Dispensed) AS Dispensed
替换Sums.Dispensed
。【参考方案2】:
您可能根本不需要聚合。行数没有减少,所以这可能是你想要的:
SELECT cr.FK_CartridgeRegistration_Id AS ID,
d.Dispensed, cr.Amount AS Refilled
FROM CartridgeRefillItem cr CROSS APPLY
(SELECT SUM(cd.Amount) AS Dispensed
FROM CartridgeDispenseAttempt c
WHERE cr.FK_CartridgeRefill_Id = cd.FK_CartridgeRefill_Id
) d;
我希望您希望每个 id 都有单独的总数。如果是这样,那么您的示例结果是不明智的,因为 id
s 重复了。但这似乎会做一些有用的事情:
select id, sum(refill_amount) as refill_amount,
sum(dispensed_amount) as dispensed_amount
from ((select cr.FK_CartridgeRegistration_Id as id,
cr.Amount as refill_amount,
0 as dispensed_amount
from CartridgeRefillItem cr
) union all
(select cd.FK_CartridgeRegistration_Id as id,
0, cd.Amount
from CartridgeDispenseAttempt cd
)
) c
group by id
【讨论】:
以上是关于可以在一个交叉应用中使用两个聚合吗?的主要内容,如果未能解决你的问题,请参考以下文章