【问题标题】:Listing of all elements recursively through postgresql通过postgresql递归列出所有元素
【发布时间】:2015-06-23 09:13:43
【问题描述】:

在我的数据库中,我基本上有一个名为 person 的表(Doctrine 的实体),它看起来像这样:

class Person
{
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Person")
     */
    private $parent;
}

我想构建一个方法getAllChildren,它返回person1 下的所有人员,并递归返回所有有孩子的人员。

我想知道我是否可以通过一个递归的SQL 请求来做到这一点。

更新1

postgres 版本:9.1

  -- Table: person

  -- DROP TABLE person;

  CREATE TABLE person
  (
      id serial NOT NULL,
      parent_id integer,
      nom character varying(255) DEFAULT NULL::character varying,
      prenom character varying(255) DEFAULT NULL::character varying,
      age integer,
      description text,
      statut character varying(255) DEFAULT NULL::character varying,
      CONSTRAINT person_pkey PRIMARY KEY (id),
      CONSTRAINT fk_7cbkzkd63HRzVK8e FOREIGN KEY (parent_id)
      REFERENCES person(id) MATCH SIMPLE
  )

更新2

我找到了http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/,这正是我所需要的除了我的模型是无限的

【问题讨论】:

  • 是的,你可以。但如果你想要一个 SQL 答案,请提供 SQL 详细信息:至少是表定义,最好是一些示例数据和 PG 版本。
  • @Patrick 请查看我更新的帖子
  • 您的 DDL 不完整:CONSTRAINT fk_7cbkzkd63HRzVK8e FOREIGN KEY (parent_id) REFERENCES person(id)

标签: php sql postgresql doctrine-orm


【解决方案1】:

在 PostgreSQL 中,您可以使用 recursive CTE 优雅地处理表级别的递归。对于您的具体问题,解决方案是这样的(根据需要从表中添加其他列;为简洁起见,此处省略):

WITH RECURSIVE p(parent, child, refs) AS (
  SELECT parent_id, id, 1 FROM person WHERE parent_id IS NOT NULL
UNION
  SELECT parent_id, child, refs+1 
  FROM person JOIN p ON id = parent)
SELECT * FROM p WHERE parent IS NOT NULL 
ORDER BY parent, child;

这里的诀窍是你必须按照自己的方式向上层次结构才能找到更深层次的关系; refs 列表示parentchild 之间的分隔。 (如果您从任何给定的person.id向下层次结构,由于递归 CTE 的工作方式,AFAIK,您不能链接超过 1 个级别。您可能可以,但可能不是就像上面的解决方案一样优雅。)

我发现包含自我引用通常很有用,即包含parent = childrefs = 0 的记录。那么解决方案就变成了:

  WITH RECURSIVE p(parent, child, refs) AS (
    SELECT id, id, 0 FROM person WHERE parent_id IS NOT NULL   -- the self-reference
  UNION
    SELECT parent_id, child, refs+1 
    FROM person JOIN p ON id = parent)
  SELECT * FROM p WHERE parent IS NOT NULL 
UNION
  SELECT id AS parent, id AS child, 0 AS refs   -- add the top-level node
  FROM person
  WHERE parent_id IS NULL
ORDER BY parent, child;

为了便于使用,您可以将查询包装在视图中,然后您只需在 Doctrine 中创建视图的实体即可获取数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    相关资源
    最近更新 更多