SQL Server父/子排序(可能的递归?)

时间:2013-11-24 14:13:39

标签: sql sql-server

我想生成一个查询,列出父节点及其每个子节点和子节点(等等)彼此之下。与使用回复和回复构建评论的方式完全相同。

例如,鉴于此数据:

ID    ParentID
--------------
1    0
2    0
3    2
4    2
5    0
6    1
7    2
8    7

我想得到一个像这样结构的查询:

ID    ParentID
--------------
1    0
6    1
2    0
3    2
4    2
7    2
8    7
5    0

我知道我需要一个递归CTE我相信,但是怎么样?

由于

3 个答案:

答案 0 :(得分:1)

好像你想对存储在表格中的树结构进行DFS(深度优先搜索)。

                0
             /  |  \
            /   |   \
           /    |    \
          /     |     \
         1      2      5
         |    / | \
         6   3  4  7
                   |
                   8

您的代码的逻辑是:

DFS(Node p){
    children = GetChildren(p)
    foreach (c in children) {
        Print("ID: " + c + " Parent ID: " + p)
        DFS(c)
    }
}

现在是SQL Server。 选择直接作为给定节点子节点的节点很简单:

SELECT [ID] FROM [Table] WHERE [ParentID] = @parentID

创建临时表以存储结果:

CREATE TABLE #temp(ID int, ParentID int);

然后递归SELECT INTO结果表或在while循环中执行。

答案 1 :(得分:1)

SQL2008 +:

DECLARE @MyTable TABLE
(   
    ID INT PRIMARY KEY,
    ParentID INT NOT NULL
);
INSERT  @MyTable (ID, ParentID)
          SELECT 1, 0
UNION ALL SELECT 2, 0
UNION ALL SELECT 3, 2
UNION ALL SELECT 4, 2
UNION ALL SELECT 5, 0
UNION ALL SELECT 6, 1
UNION ALL SELECT 7, 2
UNION ALL SELECT 8, 7;

WITH ConvertAdiacentListToHierarchyID
AS
(
SELECT  x.ID, x.ParentID, CONVERT(VARCHAR(8000), '/' + CONVERT(VARCHAR(10), x.ID) + '/') AS Node
FROM    @MyTable x
WHERE   x.ParentID = 0
UNION ALL
SELECT  x.ID, x.ParentID, CONVERT(VARCHAR(8000), y.Node + CONVERT(VARCHAR(10), x.ID) + '/') AS Node
FROM    @MyTable x 
INNER JOIN ConvertAdiacentListToHierarchyID y ON x.ParentID = y.ID
)
SELECT  cte.*, CONVERT(HIERARCHYID, cte.Node) AS NodeAsHierachyID
FROM    ConvertAdiacentListToHierarchyID cte
ORDER BY NodeAsHierachyID;

结果:

ID ParentID Node    NodeAsHierachyID
-- -------- ------- ----------------
1  0        /1/     0x58
6  1        /1/6/   0x5CA0
2  0        /2/     0x68
3  2        /2/3/   0x6BC0
4  2        /2/4/   0x6C20
7  2        /2/7/   0x6CE0
8  7        /2/7/8/ 0x6CF440
5  0        /5/     0x8C

答案 2 :(得分:0)

尝试这样的事情......

;WITH
  cte (EmpID, ParentID, EmpLevel)
  AS
  (
    SELECT ID, ParentID, 1
    FROM Table
    WHERE ParentID = 0

    UNION ALL

    SELECT t.ID, t.ParentID,c.EmpLevel + 1
    FROM Table t
      INNER JOIN cte c
        ON t.ParentID = c.EmpID
  )
SELECT
  EmpID,EmpLevel
FROM cte
ORDER BY EmpID,EmpLevel