我需要在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中有相同的错误?
答案 0 :(得分:1)
在开始递归CTE之前,您需要了解几件事
DISTINCT
或UNION
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