我有两个基本实体:财务计划和采购请求。这两个实体是多对多关系:
CREATE TABLE FinancialPlan
(
ID int NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE PurchaseRequest
(
ID int NOT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE FP_PR
(
FP_ID FOREIGN KEY REFERENCES FinancialPlan(ID),
PR_ID FOREIGN KEY REFERENCES PurchaseRequest(ID)
);
问题:查找与指定计划相关的所有请求,以及与请求相关、与指定计划相关的所有计划,...
模型可以表示为一个图,其中每个节点代表一个计划,或一个请求,每条边代表一种关系,那么问题可以改写为找到指定节点所属的连通组件强>.
例子:
Plan Request FP_PR
ID | ID | FP_ID|PR_ID|
----| ----| -----|-----|
1 | 1 | 1 |1 |
2 | 2 | 2 |1 |
3 | 3 | 2 |2 |
4 | 3 |2 |
5 | 4 |2 |
5 |3 |
查找 finplan ID=1 的连通分量
期望的输出:
FP_ID | PR_ID|
------+------+
1 | 1 |
2 | 1 |
2 | 2 |
3 | 2 |
4 | 2 |
我目前在应用程序端递归执行此操作,这可能会生成许多请求并挂起数据库服务器,这可以通过一些递归数据库方法来完成吗?
最佳答案
SQL Server 解决方案
我想主要问题是您需要先按 PR_ID
进行比较,然后再按 FP_ID
进行比较。所以在递归部分必须有一个CASE
语句。在第一次运行中,我们通过 FP_ID
获取数据,在第二个运行中通过 PR_ID
等在模的帮助下获取数据。
DECLARE @fp int = 1
;WITH cte AS (
SELECT f.FP_ID,
f.PR_ID,
1 as lev
FROM #FP_PR f
WHERE f.FP_id = @fp
UNION ALL
SELECT f.FP_ID,
f.PR_ID,
lev+1
FROM cte c
CROSS JOIN #FP_PR f -- You can use INNER JOIN instead
WHERE CASE (lev+1)%2 WHEN 0 THEN f.PR_ID WHEN 1 THEN f.FP_ID END = CASE (lev+1)%2 WHEN 0 THEN c.PR_ID WHEN 1 THEN c.FP_ID END
AND NOT (f.PR_ID = c.PR_ID AND f.FP_ID = c.FP_ID)
)
SELECT *
FROM cte
输出:
FP_ID PR_ID lev
1 1 1
2 1 2
2 2 3
3 2 4
4 2 4
关于sql - 在多对多实体之间查找sql连接组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47307244/