sql - 如何在 SQL 中执行嵌套循环?
问题描述
我正在尝试计算项目的数量,其中每个项目可能有孩子的数量也将包括在内。就深度而言,树没有具体的限制,所以我需要能够循环直到没有找到一个项目的子项,然后转到该级别的下一个项目并继续计算项目计数的总和。
我可以使用以下 SQL 计算初始级别的项目总和,但我不知道如何正确循环以添加每个项目的任何子项的数量:
SELECT SUM(ShippingUnitMaterial.Quantity)
FROM ShippingUnitMaterial
WHERE ShippingUnitMaterial.ShippingUnitID =
ShippingUnit.ShippingUnitID)
AS TotalMaterialQty
我的表是这样构造的,因此一个运输单位有一个 ID 和一个 ParentID。数量 SUM 的计算如前面的 SUM 语句所示,然后我需要执行查找并为每个子项执行相同的计算(添加到主 SUM)。
在伪代码中它将是:
LOOP
FOR EACH ShippingUnitID in an input list of ShippingUnitIDs
SUM the ShippingUnitMaterial.Quantity for all records in ShippingUnitMaterial
WHERE ShippingUnitMaterial.ShippingUnitID == ShippingUnit.ShippingUnitID
create a list, ChildList, of all ShippingUnitIDs where the ParentID == ShippingUnit.ShippingUnitID
IF ChildList is not empty, call MAIN LOOP with the list
END LOOP
我可以很容易地用 C# 编写它,但是在复制 SQL 中的逻辑时遇到了麻烦。
我应该得到所有树枝数量的总和,其中每个分支都以输入列表中的 ID 开头。
示例输入列表:
3093, 3096
ShippingUnitMaterial 表的示例数据:
ShippingUnitMaterialID DeliveryID ShippingUnitID Quantity
4204 1 3093 1
4205 1 3094 2
4207 3 3099 7
4208 3 3096 4
ShippingUnitSU 表的示例数据:
ShippingUnitSUID DeliveryID ParentShippingUnitID ShippingUnitID
205 2391 3097 3093
206 2391 3093 3094
207 2391 3093 3099
208 2391 3313 3096
所需的输出将是:
For input 3093, 10
For input 3096, 4
解决方案
正如其他人所提到的,您在这里想要的是一个递归公用表表达式 (rCTE),通过父子关系进行递归,然后进行聚合。这导致以下结果:
CREATE TABLE dbo.ShippingUnitMaterial (ShippingUnitMaterialID int,
DeliveryID int,
ShippingUnitID int,
Quantity int);
CREATE TABLE dbo.ShippingUnitSU (ShippingUnitSUID int,
DeliveryID int,
ParentShippingUnitID int,
ShippingUnitID int);
INSERT INTO dbo.ShippingUnitMaterial
VALUES (4204,1,3093,1),
(4205,1,3094,2),
(4207,3,3099,7),
(4208,3,3096,4);
INSERT INTO dbo.ShippingUnitSU
VALUES (205,2391,3097,3093),
(206,2391,3093,3094),
(207,2391,3093,3099),
(208,2391,3313,3096);
GO
WITH Shippings AS (
SELECT SU.ShippingUnitID AS StartID,
NULL AS ParentID,
SU.ShippingUnitID AS ShippingID
FROM dbo.ShippingUnitSU SU
WHERE SU.ShippingUnitID IN (3093,3096)
UNION ALL
SELECT S.StartID,
S.ShippingID AS ParentID,
SU.ShippingUnitID AS ShippingID
FROM dbo.ShippingUnitSU SU
JOIN Shippings S ON SU.ParentShippingUnitID = S.ShippingID)
SELECT S.StartID,
SUM(UM.Quantity) AS TotalQuantity
FROM Shippings S
JOIN dbo.ShippingUnitMaterial UM ON S.ShippingID = UM.ShippingUnitID
GROUP BY S.StartID;
GO
DROP TABLE dbo.ShippingUnitSU;
DROP TABLE dbo.ShippingUnitMaterial;
推荐阅读
- azure - Azure 的 Speech to Text 服务是否接受 Webm 音频并提供带有时间戳的输出?
- r - 如何根据 R 中的时间矩阵对点进行排序?
- algorithm - 快速随机/突变算法(向量到向量)
- html - 页脚覆盖网站元素
- javascript - 如何在javascript中减少数组中的数字
- go - Golang 中的 Activator.CreateInstance() 类似物
- git - 远程提交如何在强制推送中幸存下来?
- python-3.x - 如何在没有特定查询的情况下使用 tweepy 的 search_full_archive
- restsharp - 如何在 RestSharp 请求中指定日期格式
- javascript - 为什么要在字符串状态检查中使用严格比较?