【问题标题】:Sort hierarchical table CTE query排序分层表 CTE 查询
【发布时间】:2012-05-15 11:19:38
【问题描述】:

如何使用 CTE 查询对分层表进行排序?

示例表:

|ID|Name  |ParentID|
| 0|      |-1      |
| 1|1     |0       |
| 2|2     |0       |
| 3|1-1   |1       |
| 4|1-2   |1       |
| 5|2-1   |2       |
| 6|2-2   |2       |
| 7|2-1-1 |5       |

我最喜欢的结果是:

|ID|Name  |ParentID|Level
| 0|      |-1      |0
| 1|1     |0       |1
| 3|1-1   |1       |2
| 4|1-2   |1       |2
| 2|2     |0       |1
| 5|2-1   |2       |2
| 7|2-1-1 |5       |3
| 6|2-2   |2       |2

另一个示例:

另一个样本:

|ID|Name      |ParentID|
| 0|          |-1      |
| 1|Book      |0       |
| 2|App       |0       |
| 3|C#        |1       |
| 4|VB.NET    |1       |
| 5|Office    |2       |
| 6|PhotoShop |2       |
| 7|Word      |5       |

我最喜欢的结果是:

|ID|Name      |ParentID|Level
| 0|          |-1      |0
| 1|Book      |0       |1
| 3|C#        |1       |2
| 4|VB.NET    |1       |2
| 2|App       |0       |1
| 5|Office    |2       |2
| 7|Word      |5       |3
| 6|PhotoShop |2       |2

【问题讨论】:

  • 这是什么规则?这是按名称排序的,而不是按级别排序的。

标签: tsql hierarchy


【解决方案1】:

hierarchyid 数据类型能够表示分层数据,并且已经具有所需的排序顺序。如果您无法替换您的 ParentID 列,那么您可以即时转换为它:

(这个脚本大部分是数据设置,实际答案很小)

declare @t table (ID int not null,Name varchar(10) not null,ParentID int not null)
insert into @t(ID,Name,ParentID)
select 0,''          ,-1 union all
select 1,'Book'      ,0  union all
select 2,'App'       ,0  union all
select 3,'C#'        ,1  union all
select 4,'VB.NET'    ,1  union all
select 5,'Office'    ,2  union all
select 6,'PhotoShop' ,2  union all
select 7,'Word'      ,5

;With Sensible as (
    select ID,Name,NULLIF(ParentID,-1) as ParentID
    from @t
), Paths as (
    select ID,CONVERT(hierarchyid,'/' + CONVERT(varchar(10),ID) + '/') as Pth
    from Sensible where ParentID is null
    union all
    select s.ID,CONVERT(hierarchyid,p.Pth.ToString() + CONVERT(varchar(10),s.ID) + '/')
    from Sensible s inner join Paths p on s.ParentID = p.ID
)
select
    *
from
    Sensible s
        inner join
    Paths p
        on
            s.ID = p.ID
order by p.Pth

【讨论】:

    【解决方案2】:

    ORDER BY Name 应该可以正常工作:

    WITH CTE 
    AS(
        SELECT parent.*, 0 AS Level
        FROM @table parent
        WHERE parent.ID = 0
    
        UNION ALL
    
        SELECT parent.*, Level+1
        FROM @table parent
        INNER JOIN CTE prev ON parent.ParentID = prev.ID
    )
    
    SELECT * FROM CTE 
    ORDER BY Name
    

    这是您的示例数据(下次自己添加):

    declare @table table(ID int,Name varchar(10),ParentID int);
    insert into @table values(0,'',-1);
    insert into @table values(1,'1',0);
    insert into @table values(2,'2',0);
    insert into @table values(3,'1-1',1);
    insert into @table values(4,'1-2',1);
    insert into @table values(5,'2-1',2);
    insert into @table values(6,'2-2',2);
    insert into @table values(7,'2-1-1',5);
    

    结果:

    ID  Name    ParentID    Level
    0             -1          0
    1    1         0          1
    3    1-1       1          2
    4    1-2       1          2
    2    2         0          1
    5    2-1       2          2
    7    2-1-1     5          3
    6    2-2       2          2
    

    【讨论】:

    • 此表为示例,“名称”字段可能是每个字符
    • @Mehdi:然后提供更好的样本。实际上,尚不清楚您的规则是什么。你想怎么点?
    猜你喜欢
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多