我有两张桌子:
数据样本:
Account | Amount
--------+---------
001 | $100
002 | $150
003 | $200
004 | $300
Account | Related Account
--------+------------------
001 | 002
002 | 003
003 | 002
我的目标是能够汇总所有相关帐户。从表二 - 001,002& 003实际上都是彼此相关的。我希望能够获得所有相关帐户的总和。可能是ID 001到003的帐号#1,所以我可以聚合它们。
以下结果
ID | Account | Amount
-----+-----------+--------
#1 | 001 | $100
#1 | 002 | $150
#1 | 003 | $200
#2 | 004 | $300
然后我可以操作上面的表格(最终结果)
ID | Amount
-----+--------
#1 | $450
#2 | $300
我尝试过加入,但它并没有达到我想要的效果。我仍然有一个问题,关于帐户001与003(他们是间接相关的,因为002与001和003都有关。
如果有人能指出我正确的方向,将不胜感激。
答案 0 :(得分:2)
嗯,你真的应该更加努力。
如果您可以更改第二个表中的数据,那么它将不包含反向重复项(在您的样本数据中 - 2,3和3,2),这将简化解决方案。
如果您可以将两个表重构为单个表,related
列是自引用可为空的外键,则可以进一步简化解决方案。
让我们假设你不能做一分钟,你必须按照提供的方式处理数据。所以你要做的第一件事是忽略第二个表中的反向重复。这可以使用公共表表达式和几个case表达式来完成。
首先,创建并填充样本表(请在将来的问题中保存此步骤):
DECLARE @TAccount AS TABLE
(
Account int,
Amount int
)
INSERT INTO @TAccount (Account, Amount) VALUES
(1, 100),
(2, 150),
(3, 200),
(4, 300)
DECLARE @TRelatedAccounts AS TABLE
(
Account int,
Related int
)
INSERT INTO @TRelatedAccounts (Account, Related) VALUES
(1,2),
(2,3),
(3,2)
您只想从@TRelatedAccounts
表中获取前两个记录
这是 AccountAndRelated
CTE
现在,您想要将@TAccount
表加入此查询的结果,因此对于每个帐户,如果帐户与任何其他帐户无关,我们将拥有帐户,金额和相关帐户或NULL帐户或它是关系链中的第一个。
这是 CTERecursiveBase
CTE
然后,基于此,您可以创建递归CTE(称为 CTERecursive
),最后根据递归的根选择递归CTE的总和。
这是整个脚本:
;WITH AccountAndRelated AS
(
SELECT DISTINCT CASE WHEN Account > Related THEN Account Else Related END As Account,
CASE WHEN Account > Related THEN Related Else Account END As Related
FROM @TRelatedAccounts
)
, CTERecursiveBase AS
(
SELECT A.Account, Related, Amount
FROM @TAccount As A
LEFT JOIN AccountAndRelated As R ON A.Account = R.Account
)
, CTERecursive AS
(
SELECT Account As Id, Account, Related, Amount
FROM CTERecursiveBase
WHERE Related IS NULL
UNION ALL
SELECT Id, B.Account, B.Related, B.Amount
FROM CTERecursiveBase AS B
JOIN CTERecursive AS R ON B.Related = R.Account
)
SELECT Id, SUM(Amount) As TotalAmount
FROM CTERecursive
GROUP BY Id
结果:
Id TotalAmount
1 450
4 300
You can see a live demo on rextester.
现在,我们假设您可以修改第二个表的数据。您可以使用AccountAndRelated
cte获取您需要保留在@TRelatedAccounts
表中的记录 - 这意味着您可以跳过AccountAndRelated
cte并直接使用@TRelatedAccounts
CTERecursiveBase
cte。
You can see a live demo of that as well.
最后,我们假设您可以重构数据库。在这种情况下,我建议将两个表一起加入 - 所以你的@TAccount
表看起来像这样:
Account Amount Related
1 100 NULL
2 150 1
3 200 2
4 300 NULL
然后你只需要递归cte。 Here is a live demo of that option as well.