我有以下表结构,
Create Table Nodes
(
NodeID int,
ParentNodeID int, // null if root node
NodeText nvarchar(100),
NodeCost int
)
现在我需要做一些复杂的事情。从此表中查找最佳路径(具有最佳成本的路径)的成本。
有两种方法,我不确定使用哪种方式:
isLeaf
列并使用CTE来完成这项工作。isLeaf
字段,但很难找到完成此任务的SQL语句。给定的两种替代方法的优点和缺点是什么?在性能等方面哪种做法更好?
答案 0 :(得分:2)
在看到没有指定使用哪个RDBMS之前,我已经写了答案。这对于SQL Server来说,相同或类似的东西应该在Postrge和Oracle中有效,但在MySQL中则不行。
无论如何,无论哪种方式(自下而上或自上而下)都没问题,你也不必添加isLeaf
级别列,因为你可以简单地找到带有NOT IN或NOT EXISTS子查询的叶级节点 - 和如果您只对从上到下的路径感兴趣,那么您需要以两种方式获取该信息。
以下是自上而下搜索的示例查询:
;WITH rCTE AS
(
SELECT NodeID ,
ParentNodeID ,
CAST(NodeID AS NVARCHAR(MAX)) AS PathIDs,
CAST(NodeText AS NVARCHAR(MAX)) AS PathText,
NodeCost AS PathCost
FROM Nodes WHERE ParentNodeID IS NULL
UNION ALL
SELECT n.NodeID ,
n.ParentNodeID ,
r.PathIDs + '-' + CAST(n.NodeID AS NVARCHAR(10)) AS PathIDs,
r.PathText + '-' + n.NodeText AS PathText,
r.PathCost + n.NodeCost AS PathCost
FROM rCTE r
INNER JOIN dbo.Nodes n ON n.ParentNodeID = r.NodeID
)
SELECT PathIDs ,
PathText ,
PathCost
FROM rCTE r
WHERE NOT EXISTS (SELECT * FROM Nodes n WHERE r.NodeID = n.ParentNodeID)
ORDER BY PathCost
这是自下而上的例子:
;WITH rCTE AS
(
SELECT NodeID ,
ParentNodeID ,
CAST(NodeID AS NVARCHAR(MAX)) AS PathIDs,
CAST(NodeText AS NVARCHAR(MAX)) AS PathText,
NodeCost AS PathCost
FROM Nodes r WHERE NOT EXISTS (SELECT * FROM Nodes n WHERE r.NodeID = n.ParentNodeID)
UNION ALL
SELECT n.NodeID ,
n.ParentNodeID ,
r.PathIDs + '-' + CAST(n.NodeID AS NVARCHAR(10)) AS PathIDs,
r.PathText + '-' + n.NodeText AS PathText,
r.PathCost + n.NodeCost AS PathCost
FROM rCTE r
INNER JOIN dbo.Nodes n ON r.ParentNodeID = n.NodeID
)
SELECT PathIDs ,
PathText ,
PathCost
FROM rCTE r
WHERE r.ParentNodeID IS NULL
ORDER BY PathCost
<强> SQLFiddle DEMO - Top-Down 强>
<强> SQLFiddle DEMO - Bottom-Up 强>
在此示例中,两个查询的性能完全相同。一起运行时执行计划的50%-50%。