查询从整个表中列出具有父级,祖父级等的所有层次结构子级

时间:2018-02-07 18:29:09

标签: sql sql-server recursive-query

我有一个带有ID的基本sql表和来自同一个表的可选parentID。这有多个级别。我需要获得所有ID的列表,其中每个父母一直到顶部。

ID  | Name  | ParentID
_______________________
1     John    null
2     Doe     1
3     Mike    1
4     Neil    3
5     Sylvia  4
6     Mary    2

我需要得到一个这样的列表:

ID  | Parent | DirectParent
_______________________
2     1       1
3     1       1
4     3       1
4     1       0
5     4       1
5     3       0
5     1       0
  • 忽略任何没有父母的记录。
  • 对于每个孩子,都有与其父母之一匹配的记录
  • 有一个列可以知道哪一个父项就是它上面的那个

如何查询上表以获取此数据?

1 个答案:

答案 0 :(得分:2)

递归CTE将在这里完成工作。最棘手的部分是获取直接父位列,希望我从预期结果中正确理解逻辑。作为奖励,我为所有可能的路径添加了实际的报告层次结构列。 (此处递归深度最多为10次)

    CREATE TABLE #MyTable
    (
    ID int primary key,
    Name nvarchar (max),
    ParentID int
    )

    INSERT INTO #MyTable
    Values (1, 'John', null),
    (2, 'Doe', 1),
    (3, 'Mike', 1),
    (4, 'Neil', 3),
    (5, 'Sylvia', 4),
    (6, 'Mary', 2)

    WITH FindRoot AS
    (
        SELECT ID, ParentId, ParentId as Parent, CAST(Name AS NVARCHAR(MAX)) Path, 0 Distance
        FROM #MyTable

        UNION ALL

        SELECT P.ID, p.ParentId, c.Parent, C.Path + N' > ' + CAST(Name AS NVARCHAR(MAX)), C.Distance + 1
        FROM #MyTable P
        JOIN FindRoot C
        ON C.ID  = P.ParentId AND P.ParentId <> P.ID and C.ParentId <> c.ID 
        WHERE C.DISTANCE < 10
     )
    SELECT R.ID, R.Parent,
    CASE WHEN R1.Parent IS NULL THEN 1
    ELSE 0
    END AS DirectParent,  R.Path as ReportingHierarchy
    FROM FindRoot R
    LEFT JOIN FindRoot R1 on R1.ID = R.ID and R1.Parent =
    (SELECT Top 1 Parent From FindRoot
    WHERE ID = R.ID and Parent > R.Parent 
    Order by Parent)
    WHERE  R.Distance >= 0 and R.ParentId is not null
    Order by R.ID, R.distance
    option(maxrecursion 10)

结果如下:

    +----+--------+--------------+----------------------+
    | ID | Parent | DirectParent |  ReportingHierarchy  |
    +----+--------+--------------+----------------------+
    |  2 |      1 |            1 | Doe                  |
    |  3 |      1 |            1 | Mike                 |
    |  4 |      3 |            1 | Neil                 |
    |  4 |      1 |            0 | Mike > Neil          |
    |  5 |      4 |            1 | Sylvia               |
    |  5 |      3 |            0 | Neil > Sylvia        |
    |  5 |      1 |            0 | Mike > Neil > Sylvia |
    |  6 |      2 |            1 | Mary                 |
    |  6 |      1 |            0 | Doe > Mary           |
    +----+--------+--------------+----------------------+

修改 应该提到这一点,但根据对此答案的评论 - 确保您已将ParentIDID列编入索引。