Order SQL results where each record referencing another record on the same table comes after the referenced record

ⅰ亾dé卋堺 提交于 2021-02-11 14:27:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!