Php 通过postgresql递归列出所有元素
在我的数据库中,我基本上有一个名为person的表(用于Php 通过postgresql递归列出所有元素,php,sql,postgresql,doctrine-orm,Php,Sql,Postgresql,Doctrine Orm,在我的数据库中,我基本上有一个名为person的表(用于原则的实体),它看起来如下: class Person { private $id; /** * @ORM\ManyToOne(targetEntity="Person") */ private $parent; } 我想构建一个mé方法getAllChildren,它返回person1下的所有人,并递归返回有孩子的人下的所有人 我想知道是否可以通过一个递归的SQL请求来实现这一点。 更新1
原则的实体),它看起来如下:
class Person
{
private $id;
/**
* @ORM\ManyToOne(targetEntity="Person")
*/
private $parent;
}
我想构建一个mé方法getAllChildren
,它返回person1
下的所有人,并递归返回有孩子的人下的所有人
我想知道是否可以通过一个递归的SQL
请求来实现这一点。
更新1
博士后版本: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
我发现,这正是我所需要的,除了我的模型是无限的在PostgreSQL中,您可以使用一个函数在表级优雅地处理递归。对于您的特定问题,解决方案如下(根据需要添加表中的其他列;为了简洁和重点,此处省略):
这里的诀窍是,为了找到更深层次的关系,你必须按照自己的方式提升层次;refs
列指示父项
和子项
之间的分隔。(如果您从任何给定的person.id
向下查看层次结构,那么由于递归CTE的工作方式,您不能链接到超过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;
为了便于使用,您可以将查询包装在视图中,然后只需在条令中创建视图的实体即可获取数据。是的,您可以。但是,如果您想要SQL答案,请提供SQL详细信息:表定义至少,最好是一些示例数据和PG版本。@Patrick请查看我更新的帖子您的DDL不完整:CONSTRAINT fk_7cbkzkd63HRzVK8e外键(父项id)引用个人(id)
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;