Order SQL结果,其中引用同一表上另一条记录的每条记录位于被引用记录之后
我有以下数据:Order SQL结果,其中引用同一表上另一条记录的每条记录位于被引用记录之后,sql,postgresql,sql-order-by,Sql,Postgresql,Sql Order By,我有以下数据: id, parent_id 1, 3 2, null 3, 2 4, 2 其中,parent_id是对同一表的引用 我需要对这些列进行排序,以便每个记录都在其父记录之后(不一定紧跟其后) 因此,我预计会有这样的结果: id, parent_id 2, null 3, 2 1, 3 4, 2 我猜在没有任何重大模式更改的情况下,没有一种干净有效的方法可以做到这一点,但如果任何人都能想到一种方法,我会在这里提出这个问题 一种可能的方法是执行多个查询,其中每次父id都必须位于以前的
id, parent_id
1, 3
2, null
3, 2
4, 2
其中,parent_id是对同一表的引用
我需要对这些列进行排序,以便每个记录都在其父记录之后(不一定紧跟其后)
因此,我预计会有这样的结果:
id, parent_id
2, null
3, 2
1, 3
4, 2
我猜在没有任何重大模式更改的情况下,没有一种干净有效的方法可以做到这一点,但如果任何人都能想到一种方法,我会在这里提出这个问题
一种可能的方法是执行多个查询,其中每次父id都必须位于以前的查询结果之一中。但这样做效率不高。您需要递归才能完成此任务:
with recursive hier as (
select *, 0 as hlevel
from idparent
where parent_id is null
union all
select c.*, p.hlevel + 1
from hier p
join idparent c on p.id = c.parent_id
)
select * from hier
order by hlevel;
id | parent_id | hlevel
----+-----------+--------
2 | | 0
3 | 2 | 1
4 | 2 | 1
1 | 3 | 2
(4 rows)
您将需要递归来完成以下任务:
with recursive hier as (
select *, 0 as hlevel
from idparent
where parent_id is null
union all
select c.*, p.hlevel + 1
from hier p
join idparent c on p.id = c.parent_id
)
select * from hier
order by hlevel;
id | parent_id | hlevel
----+-----------+--------
2 | | 0
3 | 2 | 1
4 | 2 | 1
1 | 3 | 2
(4 rows)
我认为最安全的方法是使用递归CTE来计算每个
id
的路径。然后只需排序:
with recursive cte as (
select id, parent_id, array[id] as path
from t
where parent_id is null
union all
select t.id, t.parent_id, path || array[t.id]
from cte join
t
on cte.id = t.parent_id
)
select *
from cte
order by path;
是一个dbfiddle。我认为最安全的方法是使用递归CTE来计算每个
id
的路径。然后只需排序:
with recursive cte as (
select id, parent_id, array[id] as path
from t
where parent_id is null
union all
select t.id, t.parent_id, path || array[t.id]
from cte join
t
on cte.id = t.parent_id
)
select *
from cte
order by path;
是个傻瓜。我很惊讶你竟然不接受这个答案。很抱歉,戈登,我同样喜欢这两个答案,但迈克先回答,所以我改了。如果你比Jon Skeet落后1分,我会把我的答案改回来:我很惊讶你竟然不接受这个答案。很抱歉,戈登,我同样喜欢这两个答案,但迈克先回答,所以我改了。如果你比Jon Skeet落后1分,我会改变我的回答:P