【问题标题】:SQL Server - Order Data Hierarchy From TableSQL Server - 从表中排序数据层次结构
【发布时间】:2017-06-13 18:46:34
【问题描述】:

我有一个结构如下的表:

|  ObjectID  |  ParentID |  Description  |  Level  |
----------------------------------------------------
|  1000      |  NULL     |  Food         |  0      |
|  1001      |  1000     |  Fruit        |  1      |
|  1002      |  1000     |  Vegetable    |  1      |
|  1003      |  1001     |  Apple        |  2      |
|  1004      |  1001     |  Banana       |  2      |
|  1005      |  1002     |  Cabbage      |  2      |
|  1006      |  1002     |  Spinach      |  2      |
|  1007      |  1003     |  Red          |  3      |
|  1008      |  1003     |  Green        |  3      |
|  1009      |  1007     |  Single       |  4      |
|  1010      |  1007     |  Bunch        |  4      |
|  1011      |  1010     |  Organic      |  5      |
|  1012      |  1010     |  Non-Organic  |  5      |

它基本上在一个表中列出了一堆具有层次结构的对象。 现在我需要能够查询该表并提出基于单个ObjectID 的层次结构。像这样:

在本例中,我需要获取“Ap​​ple”层次结构下的所有内容,以便结果集为:

|  ObjectID  |  ParentID |  Description  |  Level  |
----------------------------------------------------
|  1003      |  1001     |  Apple        |  2      |
|  1007      |  1003     |  Red          |  3      |
|  1009      |  1007     |  Single       |  4      |
|  1010      |  1007     |  Bunch        |  4      |
|  1011      |  1010     |  Organic      |  5      |
|  1012      |  1010     |  Non-Organic  |  5      |
|  1008      |  1003     |  Green        |  3      |

请注意这是如何按级别对行进行排序的,其中直接子级排在父级之后。

非常感谢您的帮助!谢谢!

【问题讨论】:

标签: sql sql-server tsql hierarchy sql-server-2016


【解决方案1】:
Declare @Top int = 1003  --<<  Set To NULL for Full Hier

;with cteP as (
      Select [ObjectID]
            ,[ParentId]
            ,[Level]
            ,[Description] 
            ,[Sequence]  = cast(10000+Row_Number() over (Order by [ObjectID]) as varchar(500))
      From   @YourTable 
      Where  IsNull(@Top,-1) = case when @Top is null then isnull([ParentId] ,-1) else [ObjectID] end
      Union  All
      Select r.[ObjectID]
            ,r.[ParentId]
            ,r.[Level]
            ,r.[Description] 
            ,cast(concat(p.[Sequence],'.',10000+Row_Number() over (Order by r.[ObjectID])) as varchar(500))
      From   @YourTable r
      Join   cteP p on r.[ParentId]  = p.[ObjectID])
Select [ObjectID]
      ,[ParentId]
      ,[Description]
      ,[Level]
 From cteP 
 Order By [Sequence]

返回

ObjectID    ParentId    Description Level
1003        1001        Apple       2
1007        1003        Red         3
1009        1007        Single      4
1010        1007        Bunch       4
1011        1010        Organic     5
1012        1010        Non-Organic 5
1008        1003        Green       3

【讨论】:

  • 非常感谢!为提高可读性而添加的嵌套代码太棒了!
  • @Smiley 我怀疑你已经明白了。我编辑以反映您想要的结果。很高兴它有帮助。
【解决方案2】:

按照联机丛书中的示例:

https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql

USE AdventureWorks2012;  
GO  
WITH DirectReports(ManagerID, EmployeeID, Title, EmployeeLevel) AS   
(  
    SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevel  
    FROM dbo.MyEmployees   
    WHERE ManagerID IS NULL  
    UNION ALL  
    SELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1  
    FROM dbo.MyEmployees AS e  
        INNER JOIN DirectReports AS d  
        ON e.ManagerID = d.EmployeeID   
)  
SELECT ManagerID, EmployeeID, Title, EmployeeLevel   
FROM DirectReports  
ORDER BY ManagerID;  
GO  

【讨论】:

    猜你喜欢
    • 2013-01-31
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 2011-08-27
    • 2023-03-29
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多