按条件排序 - 使用递归 CTE

Ordering by criteria - Using Recursive CTE

我有一个 sql table,我想按照每个元素在正下方的行中都有其代码为 parentCode 的元素的方式对其进行排序。为了更清楚地说明这个例子:

            id      name         code               parentCode

parent1      1      "element1"  "parent1code"       null
parent2      2      "element2"  "parent2code"       null
children1    3      "element3"  "children1code"    "parent1Code"
children2    4      "element4"  "children2code"    "parent2Code"
children3    5      "element5"  "children3code"    "parent1Code"

等..

我想这样订购:

  parent1    
   children1    
   children3 
 parent2   
   children2

PS: 层数不确定(child也可以是parent)

您需要使用 Common Table Expressions。如果您是 CTE 新手,以下教程将帮助您理解

https://dzone.com/articles/understanding-recursive-queries-in-postgres https://www.postgresqltutorial.com/postgresql-cte/

你应该使用 Recursive Common Table Expression 来实现这个

试试这个:

with recursive cte(id, name, code, parent, key_) as (

select id, name, code, parent, array[id] as key_   
from sample where parent is null

union all
                                                                               
select t1.id, t1.name, t1.code, t1.parent, t2.key_ || t1.id 
from sample t1 
inner join cte t2 on t1.parent=t2.id
)

select id, name, code, parent from cte order by key_ 

DEMO on Fiddle

编辑

根据您的评论详情修改

with recursive cte(id, name, code,parent,key_) as (
select id,name,code,parent,array[code] as key_   from sample where parent is null
  union all
                                                                               
select t1.id,t1.name,t1.code,t1.parent,t2.key_ || t1.parent from sample t1 inner join cte t2 on t1.parent=t2.code
)

select id, name, code,parent from cte order by key_ 

DEMO

这在 MySQL 中有点棘手。基本思想是使用递归 CTE 建立到顶部的路径,然后按路径排序。但是,您希望路径中的每个标识符都具有恒定长度以避免排序问题。而且,MySQL 不支持数组,所以这一切都必须放入一个字符串中。

所以,我会推荐这样的东西:

with recursive cte as (
      select id, name, code, parent, 
             cast(lpad(id, 4, '0') as char(255)) as path
      from sample
      where parent is null 
      union all
      select s.id, s.name, s.code, s.parent, 
             concat(cte.path, '->', lpad(s.id, 4, '0'))
      from cte join
           sample s 
           on s.parent = cte.code
     )
select *
from cte
order by path;

Here 是一个 db<>fiddle.

注意:这会将 ID 扩展为四个字符。这很容易修改。