可以在一个交叉应用中使用两个聚合吗?

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 都有单独的总数。如果是这样,那么您的示例结果是不明智的,因为 ids 重复了。但这似乎会做一些有用的事情:

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

【讨论】:

以上是关于可以在一个交叉应用中使用两个聚合吗?的主要内容,如果未能解决你的问题,请参考以下文章

移动聚合广告平台KeyMob:推出广告聚合应用交叉推广等功能

移动广告聚合平台KeyMob:应用交叉推广功能上线了

KeyMob移动广告聚合的新玩法-应用交叉推广

KeyMob移动广告聚合的新玩法-应用交叉推广

我可以在猫鼬聚合之前使用填充吗?

Maven继承和聚合