我有一个SQL Server中的表,它具有Item_ID,Item_ParentID的普通树结构。 假设我想迭代并获取特定Item_ID的所有CHILDREN(任何级别)。在SQL Server中递归是否好?
递归似乎是这个问题的直觉候选人,我可以写一个SQL Server函数来做到这一点。
如果我的表有许多记录,这会影响性能吗? 如何避免递归并简单地查询表格?请提出任何建议?
我有一个SQL Server中的表,它具有Item_ID,Item_ParentID的普通树结构。 假设我想迭代并获取特定Item_ID的所有CHILDREN(任何级别)。在SQL Server中递归是否好?
递归似乎是这个问题的直觉候选人,我可以写一个SQL Server函数来做到这一点。
如果我的表有许多记录,这会影响性能吗? 如何避免递归并简单地查询表格?请提出任何建议?
随着新的MS SQL 2005,你可以使用关键字WITH
使用Oracle,您可以使用CONNECT BY
关键字来生成分层查询(syntax)。
AFAIK与MySQL你将不得不使用递归。
或者你总是可以建立一个缓存表
也许一些更多的细节是为了。
如果您有描述的主从关系,那么不会有简单的JOIN获得您所需要的吗?
如:
SELECT
SOME_FIELDS
FROM
MASTER_TABLE MT
,CHILD_TABLE CT
WHERE CT.PARENT_ID = MT.ITEM_ID
是否使用SQL 2005的记录父 - >子的关系?
如果是这样你可以使用公共表表达式来做到这一点。沿着这些路线的东西:
;
with CTE (Some, Columns, ItemId, ParentId) as
(
select Some, Columns, ItemId, ParentId
from myTable
where ItemId = @itemID
union all
select a.Some, a.Columns, a.ItemId, a.ParentId
from myTable as a
inner join CTE as b on a.ParentId = b.ItemId
where a.ItemId <> b.ItemId
)
select * from CTE
你不应该需要递归儿童 - 你只是看水平下方(即select * from T where ParentId = @parent
) - 你只需要为所有后代递归。
在SQL2005你可以得到后代,
with AllDescendants (ItemId, ItemText) as (
select t.ItemId, t.ItemText
from [TableName] t
where t.ItemId = @ancestorId
union
select sub.ItemId, sub.ItemText
from [TableName] sub
inner join [TableName] tree
on tree.ItemId = sub.ParentItemId
)
你将与递归和性能所面临的问题是,它将会有多少次改乘返回结果。每次递归调用都是另一个独立的调用,必须加入到总体结果中。
在SQL 2K5可以使用公用表表达式来处理这个递归:
WITH Managers AS
(
--initialization
SELECT EmployeeID, LastName, ReportsTo
FROM Employees
WHERE ReportsTo IS NULL
UNION ALL
--recursive execution
SELECT e.employeeID,e.LastName, e.ReportsTo
FROM Employees e INNER JOIN Managers m
ON e.ReportsTo = m.employeeID
)
SELECT * FROM Managers
或另一种解决方案是层次扁平化到另一台
Employee_Managers
经理ID(PK ,FK到Employee表)
EmployeeId(PK,FK到员工表)
米所有的父子关系的船舶将被存储在该表中,因此,如果经理1管理经理2名管理员工3,表看起来像:
ManagerId EmployeeId
1 2
1 3
2 1
这样的层次可以很容易地查询:
select * from employee_managers em
inner join employee e on e.employeeid = em.employeeid and em.managerid = 42
这将返回有经理42.所有员工的上升空间将是更高的性能,但下行空间将被维持层次
作为一般的答案,就可以做一些相当复杂的东西在SQL服务器没有只需要使用迭代算法,就需要递归。我设法在Transact SQL中做了一个XHTML解析器,它工作得非常出色。我写的代码优化器是在存储过程中完成的。它不是优雅的,它更像是看着水牛做芭蕾舞。但它的工作原理。
我曾经在Transact-SQL中写过视频播放器! :-P – 2008-10-10 14:48:54
Joe Celko有一个book(< - 链接到亚马逊)特别是在SQL数据库中的树结构。虽然您需要为您的模型递归,并且肯定会存在潜在的性能问题,但还有其他方法可以根据您的具体问题涉及哪些可以避免递归并提供更好性能的树结构建模。
你并不需要在所有的递归.... 注意,我改变了列项ID和ItemParentID便于打字...
DECLARE @intLevel INT SET @intLevel = 1INSERT INTO TempTable(ItemID, ItemParentID, Level) SELECT ItemID, ItemParentID, @intLevel WHERE ItemParentID IS NULL
WHILE @intLevel < @TargetLevel BEGIN SET @intLevel = @intLevel + 1 INSERT INTO TempTable(ItemID, ItemParentID, Level) SELECt ItemID, ItemParentID, @intLevel WHERE ItemParentID IN (SELECT ItemID FROM TempTable WHERE Level = @intLevel-1) -- If no rows are inserted then there are no children IF @@ROWCOUNT = 0 BREAK END
SELECt ItemID FROM TempTable WHERE Level = @TargetLevel
我觉得他的问题,他希望“在一个特定的水平“。除非你存储级别数字,你怎么知道什么是在一个特定的水平,没有根源= 1级,根的孩子= 2级,孩子的孩子= 3级,等等...... 不需要递归。但可能有多个父母。 – Cervo 2008-10-10 16:07:54