【问题标题】:Generate table of contents indexes based on parent-child relationships基于父子关系生成目录索引
【发布时间】:2016-09-12 06:51:17
【问题描述】:

我有一个名为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 级别对它们进行排序,因为索引 0 处的任何任务的实际位置都可能是 3.1.2。

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

谢谢

【问题讨论】:

  • MySQL 还是 Postgresql?不要标记未涉及的产品。
  • Postgresql...如果 MySQL 有问题,请删除它
  • 什么版本的 postgres?
  • 你必须使用 ctes。这是一个示例,只需将总和替换为您要获取的连接字符串:stackoverflow.com/questions/13191885/…

标签: php sql postgresql


【解决方案1】:

在 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 循环中,您只需要一个数组,该数组将路径中每个新元素的数字递增,并且当大小减少 1 时重置计数器。

这可能也可以在 SQL 中完成

另一个要考虑的选项是使用 ltree 而不是 parent_id 来存储您的关系。这将消除对 CTE 的需要

【讨论】:

  • ltree 可以非常方便地进行树操作。 (例如:Grandfather.Father.SecondChild 是您可以匹配 Grandfather.Father.* 查询的新键)这里 postgresonline.com/journal/archives/… 解释了如何简单地添加触发器,以便基于使用 id、parent_id 模型的应用程序,您最多可以日期匹配 ltree 字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 2021-02-02
  • 1970-01-01
相关资源
最近更新 更多