在我的数据库中,我基本上有一个名为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/,这几乎是我需要的除了我的模型是无限的
答案 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
列表示parent
和child
之间的分隔。 (你应该从任何给定的person.id
向下层次结构,由于递归CTE的工作方式,AFAIK,你无法链接回超过1级。你可能可以,但可能不像上面的解决方案那样优雅。)
我发现包含自引用通常很有用,即记录parent = child
和refs = 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中创建视图的实体即可获取数据。