根据父子关系生成目录索引

时间:2016-05-16 13:05:31

标签: php sql postgresql

我有一个名为task的表,它具有自我关系以完成父子关系。

这是表格的结构:

task (id, name, parent_id)

任何任务都可以有n个孩子。

现在在我看来,我必须用第n级嵌套显示目录格式的任务,如下所示:

1. Grandfather

     1.1. Father

 1.2 Mother

    1.2.1 First Child

    1.2.1 Second Child

2. Grandfather's brother

 2.1 Grandfather's brothers son 

3. Grandfather's brother's wife

为了清楚起见,我已经为人际关系命名这些任务只是为了显示嵌套的层次结构级别。

我所做的是从数据库中选择所有任务并开始迭代它们:

foreach($tasks as $task)
{
//Get the hierarchy level here and print its index for example 1.1.2
}

我不知道如何在1,2,3级别中对它们进行排序,因为索引为零的任何任务的实际位置可能是3.1.2。

可以在代码级别完成吗? 或任何SQL建议?

由于

1 个答案:

答案 0 :(得分:0)

在postgres中,您可以编写递归查询来读取全部或部分分层数据结构。

CREATE TABLE task
(
  id integer NOT NULL DEFAULT,
  name text,
  parent_id integer,
  CONSTRAINT task_pkey PRIMARY KEY (id),
  CONSTRAINT task_parent_id_fkey FOREIGN KEY (parent_id)
      REFERENCES public.task (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

insert into task values
(1, 'grandfather', null),
(2, 'father', 1),
(3, 'mother', 1),
(4, 'first child', 3),
(5, 'second child', 3),
(6, 'grandfather''s brother', null),
(7, 'grandfather''s brother''s son', 6),
(8, 'grandfather''s brother''s wife', null);

with recursive relations(relation_id, parent_id, path) as(
    select id as relation_id, null::integer as parent, ARRAY[id]::integer[], from task where parent_id is null
    union 
    select id, task.parent_id, path || id from relations
    join task on task.parent_id = relation_id

)
select * from relations
order by path

输出是:

relation_id parent_id   path
1                       {1}
2           1           {1,2}
3           1           {1,3}
4           3           {1,3,4}
5           3           {1,3,5}
6                       {6}
7           6           {6,7}
8                       {8}

现在在你的for循环中,你只需要一个数组,增加路径中每个新元素的数量,当大小减少一个时,重置计数器。

这可能也可以在SQL中完成

要考虑的另一个选择是使用ltree而不是parent_id来存储您的关系。这将摆脱对CTE的需求