具有带有非标准编号的父子关系的枚举表

时间:2019-01-27 16:31:31

标签: sql postgresql

我有一个带有两列的表(我们称它为人)

id, parent_id 

我想枚举每条记录,但为parent_id不为null的每条记录分配一个子编号,例如

id | parent_id| number 
 1     NULL       1
 2     NULL       2
 3       2        2.1
 4     NULL       3
 5       4        3.1 

父级应该有连续的数字,按id的顺序排列,子级-每个父级以1开头的连续数字。父母可能有很多孩子。但是孩子不能生孩子,因此3.3.3并非如此。 实现此目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

您应该在两个单独的查询中为父母和孩子计算行号,合并结果并连接适当的数字:

with numbers as ( 
    select *, row_number() over (partition by parent_id order by id) as rn
    from person
    where parent_id is not null
    union all
    select *, row_number() over (order by id) as rn
    from person
    where parent_id is null
)
select n1.id, n1.parent_id, concat_ws('.', n2.rn, n1.rn) as number
from numbers as n1
left join numbers as n2 on n2.id = n1.parent_id
order by n1.id

 id | parent_id | number 
----+-----------+--------
  1 |           | 1
  2 |           | 2
  3 |         2 | 2.1
  4 |           | 3
  5 |         4 | 3.1
(5 rows)    

答案 1 :(得分:1)

我只是使用窗口函数来做到这一点:

select t.*,
       concat_ws('.',
                 dense_rank() over (order by coalesce(parent_id, id)),
                 (case when parent_id is not null
                       then row_number() over (partition by parent_id order by id)
                  end)
                )
from person t
order by id;