【问题标题】:Sql Hierarchy ID Sorting By LevelSql Hierarchy ID 按级别排序
【发布时间】:2012-01-17 17:47:03
【问题描述】:

是否可以按层次结构ID对层次结构中的sql数据进行排序,然后按字母顺序对每个级别进行排序?

假设我们有一个员工表,它根据员工 ID 列出组织层次结构

您有 Bob (5),他有 Phil (17) 和 Charlie (28) 向他汇报,而 Josie (6) 有 Tyler (15) 和 Mike (56) 向她汇报。

如果您按 HierarchyID 对其进行排序,它将如下所示:

鲍勃 (/5/)
--菲尔 (/5/17/)
——查理 (/5/28/)
乔西 (/6/)
——泰勒 (/6/15/)
——迈克 (/6/56/)

但是让它看起来更有意义

鲍勃
--查理
--菲尔
乔西
--迈克
--泰勒

这是否可能而不会变得过于复杂?

【问题讨论】:

    标签: sql sql-server-2008 hierarchy hierarchyid


    【解决方案1】:

    --这行得通吗?这取自Sorting tree with other column in SQL Server 2008

    DECLARE @table TABLE (id INT NOT NULL PRIMARY KEY, name NVARCHAR(4000) NOT NULL, path HIERARCHYID)
    
    INSERT
    INTO    @table
    VALUES  
            (1, 'People', '/'),
            (2, 'Girls', '/1/'),
            (3, 'Boys', '/2/'),
            (4, 'Zoey', '/1/1/'),
            (5, 'Kate', '/1/2/'),
            (6, 'Monica', '/1/3/'),
            (7, 'Mark', '/2/1/'),
            (8, 'David', '/2/2/')
    
    ;WITH   q AS
            (
            SELECT  *, HIERARCHYID::Parse('/') AS newpath
            FROM    @table
            WHERE   path = HIERARCHYID::GetRoot()
            UNION ALL
            SELECT  t.*, HIERARCHYID::Parse(q.newpath.ToString() + CAST(ROW_NUMBER() OVER (ORDER BY t.name) AS NVARCHAR(MAX)) + '/')
            FROM    q
            JOIN    @table t
            ON      t.path.IsDescendantOf(q.path) = 1
                    AND t.path.GetLevel() = q.path.GetLevel() + 1
            )
    SELECT  replicate(convert(nvarchar, '-'), q.path.GetLevel()) + q.name /*+ '(' + q.newpath.ToString() + ')'*/
    FROM    q
    ORDER BY
            newpath
    

    【讨论】:

    • 它是一种父子关系,它必须深入。目前最深的等级是4,但如果我们真的想的话可以到400,但是谁听说过有400级的菜单。
    【解决方案2】:

    这是我找到的解决方案

    declare @oldId hierarchyid, @newId hierarchyid, @parent hierarchyid
    
    select @oldId = id_node, @parent = id_node.GetAncestor(1)
    from gbs.T_Hierarchy_Activities ha
    where ID = @ID_Object
    
    select @newId = @oldId.GetReparentedValue(@oldId, ID_Node) from (
        select row_number() over(order by id_node) rn, id_node
        from gbs.T_Hierarchy_Activities ha
            cross join (select * from common.FX_Permissions() where ID_Feature = 10) p
        where ID_Node.IsDescendantOf(@oldId.GetAncestor(1)) = 1
            and ID_Level = @oldId.GetLevel()
            and ha.ID_Office = p.ID_Office
    ) a
    where rn = @NewPosition
    
    update gbs.T_Hierarchy_Activities
    set ID_Node = case when ID_Node = @oldId then @newId else @oldId end
    where ID_Node in (@oldId, @newId)
    

    【讨论】:

      【解决方案3】:

      除非我有什么误解,否则您可以在ORDER BY 子句中添加一个辅助排序字段。例如:

      SELECT * FROM Employees ORDER BY HierarchyID, Name
      

      【讨论】:

      • 第二个订单是决胜局不是吗?如果有任何关系,那么它会按字母顺序排序。所有这些条目都将具有唯一的 HiearchyID,因此第二类不会影响我不认为的任何内容。
      • 是的,抱歉误会了。你能在你的问题中列出表定义吗? HierarchyID 只是一个字符串,它连接由斜杠分隔的每个级别吗?是否有 ManagerID 字段?
      • 这只是一个简单的例子。真正的例子是菜单(我认为员工会更容易理解)。重要字段是 Description (varchar) 和 MenuHierarchy (hierarchyID)
      猜你喜欢
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2023-03-18
      • 2021-01-27
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      相关资源
      最近更新 更多