Sql 如何按层次对行进行排序

Sql 如何按层次对行进行排序,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个具有层次结构、父子关系的表,并希望按该层次结构对其进行排序。表为: id|parent|type -------------- 1 |0 |1 2 |0 |1 3 |0 |1 4 |0 |2 5 |0 |2 6 |2 |2 7 |3 |2 因此,我希望: id|parent|type -------------- 1 |0 |1 2 |0 |1 6 |2 |2 3 |0 |1 7 |3 |2

我有一个具有层次结构、父子关系的表,并希望按该层次结构对其进行排序。表为:

id|parent|type
--------------
1 |0     |1
2 |0     |1
3 |0     |1
4 |0     |2
5 |0     |2
6 |2     |2
7 |3     |2
因此,我希望:

id|parent|type
--------------
1 |0     |1
2 |0     |1
6 |2     |2
3 |0     |1
7 |3     |2
4 |0     |2
5 |0     |2
所以我想得到一个类似于树视图的东西,其中类型1首先排序,类型2最后排序

现在我尝试使用递归,但顺序错误:

with cte as
(
  select id, parent, type from tbl where id=1
  union all
  select id, parent, type,
  ROW_NUMBER()over(
   order by
         (case when t.type = 1 then 1
            when t.type = 2 then 2
    else 1000
    end) as rn
  from tbl t
  inner join cte c on c.id=t.parent
)
select * from cte
order by rn

如何执行此操作?

可以使用以下递归CTE执行:

WITH cte AS (
  SELECT *,
    CAST(ROW_NUMBER() OVER(ORDER BY id) AS REAL) rn,
    1 level
  FROM tbl
  WHERE parent = 0
  UNION ALL
  SELECT t2.*,
    cte.rn + (CAST(ROW_NUMBER() OVER(ORDER BY t2.id) AS REAL) / POWER(10, cte.level)) rn,
    cte.level + 1 level
  FROM tbl t2 INNER JOIN cte
    ON t2.parent = cte.id
)
SELECT id, parent, type
FROM cte
ORDER BY rn
请参见更复杂的示例数据(更深层的层次结构,“无序的父子id”)

使用order by with cte很简单,而不是测试递归关系

DECLARE @Data table (Id int identity(1,1) primary key, Parent int, Type int)

INSERT @Data VALUES 
(0, 1),
(0, 1),
(0, 1),
(0, 2),
(0, 2),
(2, 2),
(3, 2)

SELECT * FROM @Data

;WITH level AS
(
    -- The root, build the hierarchy by /{Type}.{Id}/, where Type is important then Id
    SELECT *, -- 0 AS Level,
        '/' + CONVERT(varchar(max), Type + 0.1 * Id) + '/' AS Ordering 
    FROM @Data 
    WHERE Parent = 0
    UNION ALL
    -- Connect the parent with appending the hierarchy
    SELECT d.*, -- c.Level + 1, 
        c.Ordering + CONVERT(varchar(max), d.Type + 0.1 * d.Id) + '/' 
    FROM @Data d INNER JOIN level c ON d.Parent = c.Id
)
SELECT Id, Parent, Type FROM level 
ORDER BY CAST(Ordering as hierarchyid) -- The key part to convert data type

Connect By是您最好的朋友,如果您想在@istovatis创建这样一个树型表示,它真的很酷,但我使用的是MS Sql Server。您能解释一下对于4和5这样的值,应该如何解释
type=2
?例如,为什么你把它们放在6之后,而不是之前?为什么他们有这个
类型
值,首先…你能发布你的
小提琴吗?@RogerWolf我有对象类型(type1,type2,等等),type2(和3)总是type1的子对象,但是type1的对象也可以有type1的子对象。如文件夹和文件。将失败,除非数据总是那么简单。例如,超过1个嵌套级别将破坏它。这很好,但有一个细节,id可能比父id大。@Gleb-modified answer,将适用于所有更深层次,“无序的父-子id”,请参阅fiddle。这几乎是我需要的,谢谢。但还有一个问题,现在层次结构是正确的,但是类型3和类型4的对象位于类型1和类型2的对象之上。type1和type2的id也比Type3和type4小。我该怎么解决这个问题?@Gleb很高兴有更多的数据来测试你的问题。通过乘法解决了这个问题。(当v.type='typ1'时为-0.1,当v.type='type2'时为-0.1,否则为0.1结束时为-0.1)*r.id)+'/'。非常感谢。
DECLARE @Data table (Id int identity(1,1) primary key, Parent int, Type int)

INSERT @Data VALUES 
(0, 1),
(0, 1),
(0, 1),
(0, 2),
(0, 2),
(2, 2),
(3, 2)

SELECT * FROM @Data

;WITH level AS
(
    -- The root, build the hierarchy by /{Type}.{Id}/, where Type is important then Id
    SELECT *, -- 0 AS Level,
        '/' + CONVERT(varchar(max), Type + 0.1 * Id) + '/' AS Ordering 
    FROM @Data 
    WHERE Parent = 0
    UNION ALL
    -- Connect the parent with appending the hierarchy
    SELECT d.*, -- c.Level + 1, 
        c.Ordering + CONVERT(varchar(max), d.Type + 0.1 * d.Id) + '/' 
    FROM @Data d INNER JOIN level c ON d.Parent = c.Id
)
SELECT Id, Parent, Type FROM level 
ORDER BY CAST(Ordering as hierarchyid) -- The key part to convert data type