【问题标题】:Recursive CTE with tree hierarchy SQL Server具有树层次结构 SQL Server 的递归 CTE
【发布时间】:2018-12-21 09:17:22
【问题描述】:

我需要在 SQL Server 中使用递归,但我不知道如何在我的层次结构树中使用它。

我需要一些帮助来创建我的查询并了解 CTE 递归是否可行。

我的例子:

我有两个表:piece (piece_id) 和piece_equivalence(piece1_id, piece2_id)

首先,我需要从第一个表中获取所有部分:

SELECT DISTINCT p.record_id FROM piece p

其次,我需要检查该片段是否存在于第二个表中(piece1_id 或piece2_id)

SELECT DISTINCT p.record_id           
        FROM piece p
        inner join piece_equivalence pe 
ON (pe.piece1_id = p.record_id OR pe.piece2_id = p.record_id)

第三,如果该片存在,我需要检查piece1_id或piece2_id。此 ID 也可以具有等价性。 所以我也会用我的piece1_id或piece2_id检查第二步。

目前我使用参数piece1或piece2递归调用相同的函数。

带节点的图形视图:

                                                        piece_id
                                                        ___/ \___
                                                        /         \
table : piece_equivalence               piece1_id or piece2_id    piece1_id or piece2_id
                                                /       \              /         \
table : piece_equivalence       piece1_id or piece2_id    same        same        same

带有字母的图形:

           A
       ___/ \___ ________
      /         \        \
    B            C        D
   / \          / \      / \
  D   E       F   B     E   G
 /            /
G             H

A : 一块 B、C、D、E、F、G、H 是等价的。

警告:我需要在临时表中存储所有的等价物。为了避免重复输入或无限循环,我们必须检查这个临时表的数据是否存在。

编辑:

我这样做了:

WITH pieces_CTE 
AS
(
        SELECT TOP 1 p.record_id as parent,
              case when pe.piece1_id <> p.record_id then pe.piece1_id else pe.piece2_id end as enfant,
              1 as level
        FROM piece p
        inner join piece_equivalence pe ON (pe.piece1_id = p.record_id OR pe.piece2_id = p.record_id) AND pe.pertinence = 100
        AND pe.piece1_id <> pe.piece2_id
        UNION ALL       
        SELECT c.parent, case when enfant.piece1_id <> c.parent then enfant.piece1_id else enfant.piece2_id end as enfant,
        c.level+1 
        from pieces_CTE c
        INNER JOIN piece_equivalence enfant ON (enfant.piece1_id = c.parent OR enfant.piece2_id = c.parent)
        WHERE  enfant.pertinence = 100

)

SELECT * from pieces_CTE ORDER BY parent,level,enfant
OPTION (MAXRECURSION 32767)

语句终止。最大递归100已用完 在语句完成之前。

但我的记录很大,而且我的查询记录很多,我认为不可能使用具有许多冗余循环的 CTE...

但为什么我与 TOP 1 有同样的错误?

【问题讨论】:

    标签: sql-server tree common-table-expression recursive-query


    【解决方案1】:

    在开始使用递归 CTE 之前,您需要了解几件事

    • 您不能使用DISTINCTUNION
    • 您不能在 CTE 的递归部分中使用 LEFT JOIN
    • 您需要确保递归不会以死锁结束。否则,默认递归计数为 100,CTE 将终止。请看下面的例子:

      声明@MyData 表 ( SeqNo INT IDENTITY(1,1), 全名 VARCHAR(50), ManagerId INT ) 插入@MyData ( 全名 ) VALUES('CEO')

    --插入子组件

       INSERT INTO @MyData    (
    FullName,
    ManagerId    )    SELECT
    'Department Head 1',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'CEO'    UNION    SELECT
    'Department Head 2',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'CEO'    UNION    SELECT
    'Department Head 3',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'CEO'
    
       INSERT INTO @MyData    (
    FullName,
    ManagerId    )    SELECT
    'Manager 1',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'Department Head 1'    UNION    SELECT
    'Manager 2',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'Department Head 1'    UNION    SELECT
    'Manager 3',
    ManagerId = SeqNo
    FROM @MyData
        WHERE FullName = 'Department Head 3'
       ;WITH CTE    AS    (
    SELECT
        SeqNo,
        FullName,
        Manager = ISNULL(FullName,'')
        FROM @MyData
            WHERE ManagerId IS NULL
    UNION ALL
    SELECT
        MD.SeqNo,
        MD.FullName,
        Manager = ISNULL(CTE.FullName,'')
        FROM CTE
            INNER JOIN @MyData MD
                ON CTE.SeqNo = MD.ManagerId    )    SELECT
    *
    FROM CTE
    
    SeqNo       FullName                                           Manager
    ----------- -------------------------------------------------- --------------------------------------------------
    1           CEO                                                CEO
    2           Department Head 1                                  CEO
    3           Department Head 2                                  CEO
    4           Department Head 3                                  CEO
    7           Manager 3                                          Department Head 3
    5           Manager 1                                          Department Head 1
    6           Manager 2                                          Department Head 1
    

    【讨论】:

      猜你喜欢
      • 2013-11-07
      • 2023-03-24
      • 1970-01-01
      • 2017-08-29
      • 2015-11-23
      • 1970-01-01
      • 2019-03-22
      • 2017-02-04
      相关资源
      最近更新 更多