具有树层次结构SQL Server的递归CTE

时间:2018-12-21 09:17:23

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

我需要在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中有相同的错误?

1 个答案:

答案 0 :(得分:1)

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

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

    DECLARE @MyData表(     SeqNo INT IDENTITY(1,1),     全名VARCHAR(50),     ManagerId INT)        插入@MyData(     FullName)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