Рекурсивная таблица с собственной ссылкой на плоскую структуру - PullRequest
0 голосов
/ 16 октября 2019
Entity
---------
ID
TypeAID
TypeBID

TypeAID и TypeBID - это пустые поля, в которых в строке может быть одно, введены оба значения или нет, а оба IDs указывают на одну и ту же таблицу Entity.ID (собственная ссылка).

Есть ли способ пройти рекурсивную трехуровневую структуру и получить плоскую структуру отношений parent -> child, parent -> grandchild, child -> grandchild?

В этом примере первая таблица представляет собой нормальную иерархию, а вторая -желаемый плоский вывод.

Данные:

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

Ответы [ 2 ]

2 голосов
/ 16 октября 2019

Использование 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
1 голос
/ 16 октября 2019

Следующее должно работать для любого количества уровней:

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
...