递归自引用 table 到平面结构
Recursive self referenced table to flat structure
Entity
---------
ID
TypeAID
TypeBID
TypeAID
和 TypeBID
是可为空的字段,其中行可以输入一个、两个或 none 值,并且两个 IDs
都指向相同的 table Entity.ID
(自参考)。
有什么方法可以通过 3 层深层结构递归并获得 parent -> child
、parent -> grandchild
、child -> grandchild
关系的平面结构?
这是示例,其中第一个 table 是正常层次结构,第二个是所需的平面输出。
数据:
Row ID TypeAID TypeBID
1 A NULL NULL
2 B NULL NULL
3 C A NULL
4 D B C
5 E NULL C
想要的结果:
Row Parent Child
1 A C
2 A D
3 A E
4 B D
5 C D
6 C E
使用 CTE:
DECLARE @t TABLE (Id CHAR(1), TypeAId CHAR(1), TypeBId CHAR(1))
INSERT INTO @t VALUES
('A', NULL, NULL),
('B', NULL, NULL),
('C', 'A', NULL),
('D', 'B', 'C'),
('E', NULL, 'C')
-- All entities flattened
;WITH l1 AS (
SELECT t.TypeAId AS Parent, t.Id AS Child
FROM @t t
WHERE t.TypeAId IS NOT NULL
UNION
SELECT t.TypeBId AS Parent, t.Id AS Child
FROM @t t
WHERE t.TypeBId IS NOT NULL)
-- Join l1 with itself
,l2 AS (
SELECT l1.Parent, l2.Child
FROM l1 l1
INNER JOIN l1 l2 ON l2.Parent = l1.Child)
SELECT * FROM l1
UNION ALL SELECT * FROM l2
ORDER BY Parent
以下内容适用于任意数量的级别:
DECLARE @t table
(
ID char(1)
, TypeAID char(1)
, TypeBID char(1)
)
INSERT INTO @t (ID, TypeAID, TypeBID)
VALUES
('A', NULL, NULL)
, ('B', NULL, NULL)
, ('C', 'A', NULL)
, ('D', 'B', 'C')
, ('E', NULL, 'C')
;
WITH cte
AS
(
SELECT
Parent
, ID Child
FROM
(
SELECT
ID
, TypeAID
, TypeBID
FROM @t
) D
UNPIVOT
(
Parent FOR TypeID IN (
[TypeAID]
, [TypeBID]
)
) U
)
,
cte2
AS
(
SELECT
Parent
, Child
FROM cte
UNION ALL
SELECT
cte1.Parent
, cte2.Child
FROM
cte2 cte1
JOIN cte cte2 ON cte1.Child = cte2.Parent
)
SELECT
Parent
, Child
FROM cte2
ORDER BY
Parent
, Child
Entity
---------
ID
TypeAID
TypeBID
TypeAID
和 TypeBID
是可为空的字段,其中行可以输入一个、两个或 none 值,并且两个 IDs
都指向相同的 table Entity.ID
(自参考)。
有什么方法可以通过 3 层深层结构递归并获得 parent -> child
、parent -> grandchild
、child -> grandchild
关系的平面结构?
这是示例,其中第一个 table 是正常层次结构,第二个是所需的平面输出。
数据:
Row ID TypeAID TypeBID
1 A NULL NULL
2 B NULL NULL
3 C A NULL
4 D B C
5 E NULL C
想要的结果:
Row Parent Child
1 A C
2 A D
3 A E
4 B D
5 C D
6 C E
使用 CTE:
DECLARE @t TABLE (Id CHAR(1), TypeAId CHAR(1), TypeBId CHAR(1))
INSERT INTO @t VALUES
('A', NULL, NULL),
('B', NULL, NULL),
('C', 'A', NULL),
('D', 'B', 'C'),
('E', NULL, 'C')
-- All entities flattened
;WITH l1 AS (
SELECT t.TypeAId AS Parent, t.Id AS Child
FROM @t t
WHERE t.TypeAId IS NOT NULL
UNION
SELECT t.TypeBId AS Parent, t.Id AS Child
FROM @t t
WHERE t.TypeBId IS NOT NULL)
-- Join l1 with itself
,l2 AS (
SELECT l1.Parent, l2.Child
FROM l1 l1
INNER JOIN l1 l2 ON l2.Parent = l1.Child)
SELECT * FROM l1
UNION ALL SELECT * FROM l2
ORDER BY Parent
以下内容适用于任意数量的级别:
DECLARE @t table
(
ID char(1)
, TypeAID char(1)
, TypeBID char(1)
)
INSERT INTO @t (ID, TypeAID, TypeBID)
VALUES
('A', NULL, NULL)
, ('B', NULL, NULL)
, ('C', 'A', NULL)
, ('D', 'B', 'C')
, ('E', NULL, 'C')
;
WITH cte
AS
(
SELECT
Parent
, ID Child
FROM
(
SELECT
ID
, TypeAID
, TypeBID
FROM @t
) D
UNPIVOT
(
Parent FOR TypeID IN (
[TypeAID]
, [TypeBID]
)
) U
)
,
cte2
AS
(
SELECT
Parent
, Child
FROM cte
UNION ALL
SELECT
cte1.Parent
, cte2.Child
FROM
cte2 cte1
JOIN cte cte2 ON cte1.Child = cte2.Parent
)
SELECT
Parent
, Child
FROM cte2
ORDER BY
Parent
, Child