我在PostgreSQL中有下表,需要获得具有给定ID的所有人的祖先 还必须能够区分父亲和母亲的结果。
Person table - has about 1M rows, schema looks like this:
+-----+--------+--------+
| id | father | mother |
+-----+--------+--------+
| 1 | 2 | 3 |
| 2 | 4 | 5 |
| 3 | 6 | 7 |
| 4 | 8 | 9 |
| 5 | 10 | 11 |
| ... | ... | ... |
| ... | ... | ... |
+-----+--------+--------+
目前我正在循环中进行查询,每个人获得一行。
是否可以在单个查询(或2个查询)中获取所有祖先?
查询id 2的示例结果:
+----+--------+--------+
| id | father | mother |
+----+--------+--------+
| 2 | 4 | 5 |
| 4 | 8 | 9 |
| 5 | 10 | 11 |
+----+--------+--------+
答案 0 :(得分:2)
WITH recursive ParentOf (id, father, mother )
AS
(
-- Anchor query
SELECT id, father, mother
FROM test
WHERE id = ? -- e.g. 2
UNION ALL
-- Recursive query
SELECT t.id, t.father, t.mother
FROM test t
INNER JOIN ParentOf
ON t.id = ParentOf.father OR t.id = ParentOf.mother
)
-- Statement that executes the CTE
SELECT id, father, mother
FROM ParentOf;
答案 1 :(得分:0)
这是对问题的原始版本的回答。
为此目的,最简单的方法是将每个父项用一列删除。然后使用递归CTE来获取所有父母。
代码如下所示:
with recursive t as (
select 1 as id, 2 as father, 3 as mother union all
select 2, 4, 5 union all
select 3, 6, 7 union all
select 4, 8, 9 union all
select 5, 10, 11
),
parents as (
select id, father as parent from t union all
select id, mother from t
),
cte as (
select p.id, p.parent
from parents p
where id = 2 -- or whatever id you want
union all
select cte.id, p.parent
from cte join
parents p
on cte.parent = p.id
)
select *
from cte;
Here是一个SQL小提琴。
答案 2 :(得分:-1)
如果我说得对,
您可以使用JOIN
或简单的IN()
对于IN
,它将类似于:
SELECT
p.id,
p.father,
p.mother
FROM person p
WHERE
p.id = 2
OR p.id IN (SELECT father FROM person WHERE id = 2)
OR p.id IN (SELECT mother FROM person WHERE id = 2)
这会给你:
| id | father | mother |
|----|--------|--------|
| 2 | 4 | 5 |
| 4 | 8 | 9 |
| 5 | 10 | 11 |
对于JOIN
,您可以对列进行自我加入以将其与ID配对。就像这样:
SELECT
x.id as id,
x.father as father,
x.mother as mother
FROM person p
LEFT JOIN person x ON x.id = p.id OR x.id = p.father OR x.id = p.mother
WHERE
p.id = 2
这也会给你相同的结果。
从那里,您可以在WHERE子句下使用更多条件来获得正确的结果。