使用层次结构和其他列对列进行排序以进行排序

时间:2017-11-01 20:53:01

标签: postgresql sorting hierarchical-data

我有以下结构:

id,
name,
parent_id,
order_by

和条目:

 id |    name   | parent_id | order_by 
----+-----------+-----------+----------
  8 | Cat 1     |           |        1
  7 | Cat 2     |           |        2
  5 | Cat 3     |           |        3
 15 | Cat 1.1   |         8 |        1
 17 | Cat 1.2   |        15 |        2
 16 | Cat 2.1   |         8 |        1
 20 | Cat 1.2.1 |        17 |        1

我想输出:

 id |    name   | parent_id | order_by 
----+-----------+-----------+----------
  8 | Cat 1     |           |        1
 15 | Cat 1.1   |         8 |        1
 17 | Cat 1.2   |         8 |        2
 20 | Cat 1.2.1 |        17 |        1
  7 | Cat 2     |           |        2
 16 | Cat 2.1   |         7 |        1
  5 | Cat 3     |           |        3

因此,使用order_by列对主要条目(没有parent_id)进行排序,并使用order_by列对子级进行排序。

1 个答案:

答案 0 :(得分:2)

注意:我认为id = 16 parent_id应该 7 ,而不是8

您需要一个递归查询来遍历整个树。你需要一种方法来记住"主排序顺序,然后按两个不同的标准排序:一个用于"整体"排序顺序和每个子级别的顺序:

with recursive tree as (
   select id, name, parent_id, order_by as main_order, null::int as child_order
   from category
   where parent_id is null
   union all
   select c.id, c.name, c.parent_id, p.main_order, c.order_by as child_order
   from category c
     join tree p on p.id = c.parent_id
)
select *
from tree 
order by main_order, child_order nulls first;

通过将order_by从根级别带到所有子级,我们可以将属于同一个根的所有行保持在一起。然后根据假的child_order对一个根的行进行排序 - 根行将为该列提供nullnulls first将它们放在每个组的开头。

在线示例:http://rextester.com/ZVLII98217