在多个实体之间查找sql​​连接组件

时间:2017-11-15 12:19:28

标签: sql sql-server algorithm graph

我有两个基本实体:财务计划和购买请求。 Theese两个实体处于多对多的关系中:

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    |

我目前正在app端递归执行,这可能会生成许多请求并挂起数据库服务器,这可以通过一些递归数据库方法完成吗?

可视化: enter image description here 起始实体用箭头标记。 期望的输出被圈出来。

1 个答案:

答案 0 :(得分:1)

SQL Server解决方案

我想主要问题是您需要按PR_ID然后FP_ID进行比较。因此在递归部分必须有CASE语句。在1次运行中,我们在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