Select 来自基于 ID 范围的层次结构
Select from a hierarchy based on a range of ID's
我 table 持有一个层次结构,所以基本上它有 3 列:
我想要的是 select 从这个 table 通过一系列 ID,例如:
Id IN (1,4,8,18)
结果为:
In other word a row must come into result set with all of it's parents and children.
我该如何解决这个问题?
提前致谢
您可以使用递归通用 table 表达式 (CTE)。它非常擅长这类任务。下面我假设 tbl
是您的 table 的名称。
WITH UserCTE AS
(
SELECT Id, name, ParentId
FROM tbl
WHERE Id in (1,4,8,18)
UNION ALL
SELECT P.Id, P.name, P.ParentId
FROM UserCTE AS C --- C for child
JOIN tbl AS P --- P for parent
ON C.ParentId = P.Id
)
SELECT Id, name, ParentId
FROM UserCTE;
您也可以尝试使用
SELECT DISTINCT Id, name, ParentId
FROM UserCTE;
如果您注意到某些记录被多次返回。
您可以使用 CTE 来完成:
DECLARE @t TABLE ( ID INT, ParentID INT )
INSERT INTO @t
VALUES ( 1, NULL ),
( 2, 1 ),
( 3, 2 ),
( 4, 3 ),
( 6, NULL ),
( 7, 6 ),
( 8, 7 ),
( 9, 8 ),
( 10, 9 ),
( 11, 10 ),
( 13, NULL ),
( 14, 13 ),
( 15, 14 ),
( 17, NULL ),
( 18, 17 ),
( 19, 18 ),
( 20, 19 );
WITH ctep
AS ( SELECT *
FROM @t
WHERE ID IN ( 1, 4, 8, 18 )
UNION ALL
SELECT t.*
FROM @t t
JOIN ctep ON t.ParentID = ctep.ID
),
ctec
AS ( SELECT *
FROM @t
WHERE ID IN ( 1, 4, 8, 18 )
UNION ALL
SELECT t.*
FROM @t t
JOIN ctec ON t.ID = ctec.ParentID
)
SELECT * FROM ctep
UNION
SELECT * FROM ctec
这里有 2 个 CTE,用于获得 parents 和孩子。最后,您合并这 2 个结果以获得不同的行。
我有一个小错误。已编辑...
将您的任务分成两个步骤
- 找到最顶层的父级
找到所有死者
WITH ToTopParent AS
(
SELECT Id, ParentId
FROM yourTable
WHERE Id IN (1,4,8,18)
UNION ALL
SELECT T.Id, T.ParentId
FROM ToTopParent TTP
JOIN yourTable T ON TTP.ParentId = T.Id
),
AllDecedents AS
(
SELECT Id, Name, ParentID
FROM yourTable
WHERE id IN (SELECT Id FROM ToTopParent WHERE ParentId IS NULL)
UNION ALL
SELECT T.Id, T.Name, T.ParentID
FROM yourTable T
JOIN AllDecedents ON T.ParentId = AllDecedents.Id
)
SELECT * FROM AllDecedents
我 table 持有一个层次结构,所以基本上它有 3 列:
我想要的是 select 从这个 table 通过一系列 ID,例如:
Id IN (1,4,8,18)
结果为:
In other word a row must come into result set with all of it's parents and children.
我该如何解决这个问题?
提前致谢
您可以使用递归通用 table 表达式 (CTE)。它非常擅长这类任务。下面我假设 tbl
是您的 table 的名称。
WITH UserCTE AS
(
SELECT Id, name, ParentId
FROM tbl
WHERE Id in (1,4,8,18)
UNION ALL
SELECT P.Id, P.name, P.ParentId
FROM UserCTE AS C --- C for child
JOIN tbl AS P --- P for parent
ON C.ParentId = P.Id
)
SELECT Id, name, ParentId
FROM UserCTE;
您也可以尝试使用
SELECT DISTINCT Id, name, ParentId
FROM UserCTE;
如果您注意到某些记录被多次返回。
您可以使用 CTE 来完成:
DECLARE @t TABLE ( ID INT, ParentID INT )
INSERT INTO @t
VALUES ( 1, NULL ),
( 2, 1 ),
( 3, 2 ),
( 4, 3 ),
( 6, NULL ),
( 7, 6 ),
( 8, 7 ),
( 9, 8 ),
( 10, 9 ),
( 11, 10 ),
( 13, NULL ),
( 14, 13 ),
( 15, 14 ),
( 17, NULL ),
( 18, 17 ),
( 19, 18 ),
( 20, 19 );
WITH ctep
AS ( SELECT *
FROM @t
WHERE ID IN ( 1, 4, 8, 18 )
UNION ALL
SELECT t.*
FROM @t t
JOIN ctep ON t.ParentID = ctep.ID
),
ctec
AS ( SELECT *
FROM @t
WHERE ID IN ( 1, 4, 8, 18 )
UNION ALL
SELECT t.*
FROM @t t
JOIN ctec ON t.ID = ctec.ParentID
)
SELECT * FROM ctep
UNION
SELECT * FROM ctec
这里有 2 个 CTE,用于获得 parents 和孩子。最后,您合并这 2 个结果以获得不同的行。
我有一个小错误。已编辑...
将您的任务分成两个步骤
- 找到最顶层的父级
找到所有死者
WITH ToTopParent AS ( SELECT Id, ParentId FROM yourTable WHERE Id IN (1,4,8,18) UNION ALL SELECT T.Id, T.ParentId FROM ToTopParent TTP JOIN yourTable T ON TTP.ParentId = T.Id ), AllDecedents AS ( SELECT Id, Name, ParentID FROM yourTable WHERE id IN (SELECT Id FROM ToTopParent WHERE ParentId IS NULL) UNION ALL SELECT T.Id, T.Name, T.ParentID FROM yourTable T JOIN AllDecedents ON T.ParentId = AllDecedents.Id ) SELECT * FROM AllDecedents