我已经构建了一个函数/查询,该函数/查询将 [paths] 作为邻接列表返回,如下所示,它运行良好,但是我试图弄清楚如何将结果限制为仅完整的路径,而不是深度(n)的每次迭代。
例如,在下面显示的以下结果中,只有这些是有效的,我想要返回或过滤的完整路径:
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB1_Close
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB1_Open
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB2
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Close>S2-UG
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Open>S1-UG
测试
select * from fn_Get_SubTreePaths('S11', 11) order by DPath
结果
S11>S11-LG
S11>S11-LG>V613
S11>S11-LG>V613>V613_Close
S11>S11-LG>V613>V613_Close>B31A
S11>S11-LG>V613>V613_Close>B31A>B30
S11>S11-LG>V613>V613_Close>B31A>B30>B30A
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB1_Close
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB1_Open
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Close>B-GARNER>VB1>VB2
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Close
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Close>S2-UG
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Open
S11>S11-LG>V613>V613_Close>B31A>B30>B30A>V30A1>V30A1_Open>V30A2>V30A2_Open>S1-UG
换句话说 - 我如何才能确定仅包含遍历/深度中最底部项目的那些路径?
任何帮助将不胜感激!我正在阅读 Joe Celko 为 Smarties 编写的 SQL 中的树和层次结构 - 但到目前为止,我还没有思考如何正确限制结果......
这是代码;
create function [dbo].[fn_Get_SubTreePaths]( @Start varchar(20), @MaxLevels int)
returns table
as
RETURN(
WITH CTE AS (
SELECT
c.DeviceID AS Start,
CAST(d.DeviceName AS VARCHAR(2000)) AS Path,
c.ConnectedDeviceID,
1 AS Level
FROM Connections c
INNER JOIN Devices d ON d.ID=c.DeviceID
AND d.DeviceName=@Start
UNION ALL
SELECT
r.Start,
CAST(r.Path + '>'+ d.DeviceName AS VARCHAR(2000)),
--CAST(r.Path + ' -> ' + d.DeviceName + '-' + cast(r.SLevel as varchar) AS VARCHAR),
c.ConnectedDeviceID,
Level = r.Level + 1
FROM Connections c
INNER JOIN Devices d ON d.ID=c.DeviceID
and d.DeviceName<>@Start
INNER JOIN CTE r ON c.DeviceID=r.ConnectedDeviceID
AND r.Level < @MaxLevels
)
SELECT
DISTINCT a.DPath
FROM (
SELECT c.Path + '>' + ISNULL(d.DeviceName,'?') AS DPath
FROM CTE c
INNER JOIN Devices d ON d.ID=c.ConnectedDeviceID
) a
)
CREATE TABLE [dbo].[Connections](
[ID] [int] NOT NULL,
[DeviceID] [int] NULL,
[ConnectedDeviceID] [int] NULL
CONSTRAINT [PK_Connections] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Devices](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DeviceName] [varchar](50) NULL
CONSTRAINT [PK_Devices] PRIMARY KEY CLUSTERED
(
[ID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CTE 使用的视图:
ALTER view [dbo].[vw_DeviceConnections] as
select
c.ID as ID,
c.DeviceID as DeviceID,
d.DeviceName,
d.DeviceType,
c.ConnectedDeviceID as ConnDeviceID,
cd.DeviceName as ConnDeviceName,
cd.DeviceType as ConnDeviceType
from Devices d
inner join Connections c on
d.id=c.DeviceID
inner join Devices cd on
cd.id=c.ConnectedDeviceID