问题
I have the following table structure,
Create Table Nodes
(
NodeID int,
ParentNodeID int, // null if root node
NodeText nvarchar(100),
NodeCost int
)
Now I need to do a sort of complex thing. Find the cost of the best path (path which has the best cost) from this table.
There are two ways, I am not sure which one to use:
- Bottom-up search: If I choose that, I need to add a
isLeaf
column to the table and use a CTE which does the job. - Top-down search: There is no need of
isLeaf
field, however hard to come up with the SQL statement which does the job.
What are the pros and cons of the given two alternative methods? Which is the better practice in terms of performance etc.?
回答1:
I've wrote the answer before seeing it's no specified which RDBMS is used. This if for SQL Server, same or something similar should work in Postrge and Oracle, but not in MySQL.
Anyway, either way (Bottom-Up or Top-Down) is fine, and neither way you have to add isLeaf
level column because you can simply find leaf level nodes with NOT IN or NOT EXISTS subquery - and you need that info in both ways if you are interested in only paths that go from top to bottom.
Here is a sample query for top-down search:
;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
Here is example for Bottom-Up:
;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
In this examples, performance of both queries are exactly the same. 50%-50% in execution plans when run together.
来源:https://stackoverflow.com/questions/16233946/using-bottom-up-or-top-down-search-to-find-the-best-path-from-hierarchical-data