【问题标题】:Recursive self referenced table to flat structure递归自引用表到平面结构
【发布时间】:2019-10-16 13:23:12
【问题描述】:
Entity
---------
ID
TypeAID
TypeBID

TypeAIDTypeBID 是可为空的字段,其中行可以输入一个、两个或一个值,并且两个 IDs 都指向同一个表 Entity.ID(自引用)。

有什么方法可以通过 3 级深度结构递归得到parent -> childparent -> grandchildchild -> 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

【问题讨论】:

  • 是的,这是可能的。如果你想了解你需要如何提供一些细节。像样本数据和所需的输出。 minimal reproducible example
  • 任何想法从哪里开始?
  • 你必须使用公用表表达式stackoverflow.com/questions/4740748/…
  • @SeanLange 我添加了示例输入/输出。
  • 数据图片几乎一文不值。 Why?你需要一个递归 cte 来解决这个问题。

标签: sql-server recursion self-referencing-table


【解决方案1】:

使用 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

【讨论】:

    【解决方案2】:

    以下内容适用于任意数量的级别:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-25
      • 2013-11-17
      • 1970-01-01
      • 1970-01-01
      • 2014-11-24
      • 2022-10-04
      • 2022-08-20
      相关资源
      最近更新 更多