使用自下而上或自上而下搜索从分层数据中查找最佳路径

时间:2013-04-26 10:11:55

标签: sql search hierarchical-data

我有以下表结构,

Create Table Nodes
(
    NodeID int,
    ParentNodeID int, // null if root node
    NodeText nvarchar(100),
    NodeCost int
)

现在我需要做一些复杂的事情。从此表中查找最佳路径(具有最佳成本的路径)的成本。

有两种方法,我不确定使用哪种方式:

  1. 自下而上搜索:如果我选择了这一点,我需要在表格中添加isLeaf列并使用CTE来完成这项工作。
  2. 自上而下搜索:不需要isLeaf字段,但很难找到完成此任务的SQL语句。
  3. 给定的两种替代方法的优点和缺点是什么?在性能等方面哪种做法更好?

1 个答案:

答案 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%。