我有一个递归表,其中每个记录都有一个ID和一个PARENTID。 PARENTID指向同一个表中的不同ID。 SQL Server中是否有一种方法可以在一个语句中选择整个“树”?我可以编写一个递归函数来从父项跳转到所有子项,但我想在一个查询中执行此操作。
在Oracle中,它看起来像这样:
select
id,
parentid,
nodename
from
MY_SCHEMA.MY_TABLE
connect by nocycle prior parentid = id
start with id = :starting_id_number
order by
id
SQL Server的等价物是什么?
答案 0 :(得分:3)
这是我为你抛出的一个例子。它演示了使用递归公用表表达式(CTE)。
CREATE TABLE #tempTable
(
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
parentID INT NULL
)
INSERT INTO #tempTable (parentID) VALUES (null)
INSERT INTO #tempTable (parentID) VALUES (1)
INSERT INTO #tempTable (parentID) VALUES (1)
INSERT INTO #tempTable (parentID) VALUES (2)
INSERT INTO #tempTable (parentID) VALUES (3)
INSERT INTO #tempTable (parentID) VALUES (2)
INSERT INTO #tempTable (parentID) VALUES (5)
SELECT * FROM #tempTable;
WITH RecursiveTable (ID, ParentID, Level)
AS
(
--Anchor
SELECT tt.ID,
tt.ParentID,
0 AS Level
FROM #tempTable AS tt
WHERE parentID IS null
UNION ALL
--Recursive member definition
SELECT tt.ID,
tt.ParentID,
LEVEL + 1
FROM #tempTable AS tt
INNER JOIN RecursiveTable rt ON
tt.ParentID = rt.ID
)
SELECT *
FROM RecursiveTable
DROP TABLE #tempTable
编辑另外,在SQL Server 2008中,有一种名为hierarchyid的数据类型可用于实现分层数据结构。请参阅以下教程
答案 1 :(得分:2)
您可以像这样使用CTE;
CREATE TABLE TestTable
(
ID int primary key NOT NULL,
ParentID int
)
INSERT INTO TestTable VALUES (0, null)
INSERT INTO TestTable VALUES (1, 0)
INSERT INTO TestTable VALUES (2, 0)
INSERT INTO TestTable VALUES (3, 1)
INSERT INTO TestTable VALUES (4, 3)
-- Get branch
;WITH TreeRecCTE (ID, ParentID, IDPath)
AS
(
SELECT ID, ParentID, CONVERT(varchar(max), ID) As IDPath
FROM TestTable
WHERE ParentID IS NULL
UNION ALL
SELECT
Child.ID,
Child.ParentID,
Parent.IDPath + '.' + CONVERT(varchar(100),Child.ID) As IDPath
FROM TestTable As Child INNER JOIN TreeRecCTE AS Parent ON Child.ParentID = Parent.ID
)
SELECT * FROM TreeRecCTE WHERE IDPath LIKE '%.1.%' ORDER BY ParentID ASC
-- Get complete tree:
;WITH TreeRecCTE (ID, ParentID, IDPath)
AS
(
SELECT ID, ParentID, CONVERT(varchar(max), ID) As IDPath
FROM TestTable
WHERE ParentID IS NULL
UNION ALL
SELECT
Child.ID,
Child.ParentID,
Parent.IDPath + '.' + CONVERT(varchar(100),Child.ID) As IDPath
FROM TestTable As Child INNER JOIN TreeRecCTE AS Parent ON Child.ParentID = Parent.ID
)
SELECT * FROM TreeRecCTE ORDER BY ParentID ASC
答案 2 :(得分:0)
id也有这个问题,但我没有找到解决方案。 所以我创建了这个解决方法: 我添加了一个新列'tree_id',这样我的表就像这样。
treeid|id|parentid|nodename
1 |1 | null | rootOfTreeOne
1 |2 | 1 | childOfRootOne
1 |3 | 1 | secondChild
2 |4 | null | rootOfSecondTree
2 |5 | 4 | childofSecondTree
并在程序中创建了树。优点是您可以使用一个简单的单个select语句从树中获取所有节点。
select * from tree_table where tree_id = 1;
但也可能有一些存储过程可以帮助您解决问题。
希望这会有所帮助..
答案 3 :(得分:0)
我不认为你可以在你的陈述中不使用递归而逃脱它。
如果您能够(或将来参考),您可以尝试使用modified preorder tree traversal,这样您就可以执行此操作。
在这个答案中解释修改后的预订树遍历超出了范围,因为它需要一些解释和播放才能掌握。
我将指出MPTT上有更新和插入记录的开销,但选择通常效率更高。一般来说,选择比更新/插入要多得多,所以值得,但在直接进入潜水之前考虑一下你的特殊情况是值得的。
我与之相关的文章我找到了对MPTT的一个很好的解释。
答案 4 :(得分:0)
您应该能够使用公用表表达式来执行递归查询。在谷歌搜索“使用公用表表达式的递归查询”,有一篇msdn文章。
叹息不允许新用户添加超链接。
答案 5 :(得分:0)