我正在使用 SQL Server 中的一个数据集,该数据集表示节点之间的路径,其中每个节点都有一个可见性标志 (IsVisible)。 我的目标是通过跳过标记为不可见(IsVisible = 0)的节点并直接连接可见节点来压缩这些路径。例如,给定 A -> B(false) -> C(false) -> D 这样的路径,我想将其转换为 A -> D。
每条路径在我的表中表示为一对开始和结束节点,以及开始和结束节点的可见性标志。这是我的表的结构和一些示例数据:
CREATE TABLE Paths (
StartNode CHAR(1),
EndNode CHAR(1),
StartNodeIsVisible BIT,
EndNodeIsVisible BIT
);
INSERT INTO Paths (StartNode, EndNode, StartNodeIsVisible, EndNodeIsVisible) VALUES
('A', 'B', 1, 0),
('B', 'C', 0, 0),
('C', 'D', 0, 1);
想要的结果:
| StartNode | EndNode | Depth(optional) |
|-----------|---------|-----------------|
| A | D | 3 |
我尝试使用递归公共表表达式(CTE)来实现此路径压缩,但在正确跳过不可见节点并直接连接可见节点时遇到了困难。这是我尝试过的:
WITH RecursivePaths AS (
SELECT StartNode, EndNode, StartNodeIsVisible, EndNodeIsVisible, 1 AS Depth
FROM Paths
WHERE StartNodeIsVisible = 1
UNION ALL
SELECT rp.StartNode, p.EndNode, rp.StartNodeIsVisible, p.EndNodeIsVisible, Depth + 1
FROM RecursivePaths rp
JOIN Paths p ON rp.EndNode = p.StartNode
WHERE p.EndNodeIsVisible = 1 OR (p.EndNodeIsVisible = 0 AND Depth < 50)
)
SELECT *
FROM RecursivePaths
WHERE EndNodeIsVisible = 1
OPTION (MAXRECURSION 200);
我添加了选项
(MAXRECURSION 200)
,因为我得到:
声明终止。最大递归100已经用完 在语句完成之前。
虽然此代码适用于小型数据集,但路径表中的规模约为 15,000,000 行,但它会进行大量读取:约 600,000,000(我需要在中间停止它)。
问题:
您可以合并立即可用的路径和深度 >=1 的闭包
WITH RecursivePaths AS (
SELECT StartNode, EndNode, StartNodeIsVisible, EndNodeIsVisible, 1 AS Depth
FROM Paths
WHERE StartNodeIsVisible = 1 and EndNodeIsVisible = 0
UNION ALL
SELECT rp.StartNode, p.EndNode, rp.StartNodeIsVisible, p.EndNodeIsVisible, Depth + 1
FROM RecursivePaths rp
JOIN Paths p ON rp.EndNode = p.StartNode AND rp.EndNodeIsVisible = 0
WHERE p.EndNodeIsVisible = 1 OR (p.EndNodeIsVisible = 0 AND Depth < 50)
)
SELECT *
FROM RecursivePaths
WHERE EndNodeIsVisible = 1
union
SELECT *, 0
FROM Paths
WHERE StartNodeIsVisible = 1 and EndNodeIsVisible = 1