问题
I have the following data:
id, parent_id
1, 3
2, null
3, 2
4, 2
Where parent_id is a reference to the SAME table.
I need to sort these columns so that each record is after its parent (not necessarily immediately after).
So I would expect this result:
id, parent_id
2, null
3, 2
1, 3
4, 2
I'm guessing there is no clean efficient way to do this without any significant schema changes, but in case anybody can think of a method I'm asking this here.
One possible method would be to do multiple queries where each time the parent_id must be in one of the previous queries results. But this wouldn't be very efficient.
回答1:
You will need to recurse to accomplish this:
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)
回答2:
I think the safest way to do this uses a recursive CTE to calculate the path to each id
. Then just sort:
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;
Here is a db<>fiddle.
来源:https://stackoverflow.com/questions/62677233/order-sql-results-where-each-record-referencing-another-record-on-the-same-table