通过postgresql

时间:2015-06-23 09:13:43

标签: php sql postgresql doctrine-orm

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

class Person
{
    private $id;

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

我想建立一个méthodgetAllChildren,它返回person1下的所有人,并递归所有有孩子的人。

我想知道我是否可以通过一个递归SQL请求来执行此操作。

  

UPDATE1

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
  )
  

UPDATE2

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

1 个答案:

答案 0 :(得分:2)

在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中创建视图的实体即可获取数据。