Get hierarchical structure using SQL Server

后端 未结 4 552
广开言路
广开言路 2021-01-06 09:26

I have a self-referencing table with a primary key, id and a foreign key parent_id.

+------------+--------------+------+-----+-----         


        
相关标签:
4条回答
  • 2021-01-06 09:32

    I started with a query, (but when I check it now it is similar to Mark.)

    I will add it anyway, while I created also a sqlfiddle with mine and Mark query.

    WITH tList (id,name,parent_id,nameLevel)
    AS
    (
        SELECT t.id, t.name, t.parent_id, 1 AS nameLevel
        FROM t as t
        WHERE t.parent_id IS NULL
        UNION ALL
        SELECT tnext.id, tnext.name, tnext.parent_id, tList.nameLevel + 1
        FROM t AS tnext
        INNER JOIN tList AS tlist
            ON tnext.parent_id = tlist.id
    )
    SELECT id,name,isnull(parent_id,0) 'parent_id',nameLevel FROM tList order by nameLevel;
    

    A good blog: SQL Query – How to get data in Hierarchical Structure?

    0 讨论(0)
  • 2021-01-06 09:34

    i know changing the structure of a table is always a critical operation but since sql server 2008 introduced the HierarchyId Datatype i really like workig with it. Maybe have a look at:

    http://www.codeproject.com/Articles/37171/HierarchyID-Data-Type-in-SQL-Server http://www.codeproject.com/Tips/740553/Hierarchy-ID-in-SQL-Server

    I am sure you will understand quickly how to use this datatype and his functions. The SQL Code using this datatype is more structured and has better performance than CTE's.

    0 讨论(0)
  • 2021-01-06 09:37

    You can use Common Table Expressions.

    WITH LeveledSiteMap(Id, Name, Level)
    AS
    (
        SELECT Id, Name, 1 AS Level
        FROM MySiteMap
        WHERE Parent_Id IS NULL
        UNION ALL
        SELECT m.Id, m.Name, l.Level + 1
        FROM MySiteMap AS m
            INNER JOIN LeveledSiteMap AS l
            ON m.Parent_Id = l.Id
    )
    SELECT *
    FROM LeveledSiteMap
    
    0 讨论(0)
  • 2021-01-06 09:50

    Use this:

    ;WITH CTE(Id, Name, parent_id, [Level], ord) AS (
        SELECT 
            MySiteMap.Id, 
            CONVERT(nvarchar(255), MySiteMap.Name) AS Name, 
            MySiteMap.parent_id, 
            1,
            CONVERT(nvarchar(255), MySiteMap.Id) AS ord
        FROM MySiteMap
        WHERE MySiteMap.parent_id IS NULL
        UNION ALL
        SELECT 
            MySiteMap.Id, 
            CONVERT(nvarchar(255), REPLICATE(' ', [Level]) + '|' + REPLICATE(' ', [Level]) + MySiteMap.Name) AS Name, 
            MySiteMap.parent_id, 
            CTE.[Level] + 1,
            CONVERT(nvarchar(255),CTE.ord + CONVERT(nvarchar(255), MySiteMap.Id)) AS ord
        FROM MySiteMap
            JOIN CTE ON MySiteMap.parent_id =CTE.Id
        WHERE MySiteMap.parent_id IS NOT NULL
    )
    SELECT Name
    FROM CTE
    ORDER BY ord
    

    For this:

    A
     | B
      |  B1
      |  B2
     | C
      |  C1
      |  C2
     | D
      |  D1
      |  D2
    
    0 讨论(0)
提交回复
热议问题