按条件排序 - 使用递归 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_
编辑
根据您的评论详情修改
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_
这在 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 扩展为四个字符。这很容易修改。
我有一个 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_
编辑
根据您的评论详情修改
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_
这在 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 扩展为四个字符。这很容易修改。