我使用SQL来存储有关家谱的信息。我希望能够输入出生在 X世代中的人的姓名,并输出所有出生在 Z世代中的后代的姓名,但只输出这些后代是兄弟姐妹(拥有相同的父母)。我找到了类似的解决方案,但我发现这些解决方案不适用于分层结构(由于别名)。可能还有一个父母和他们的孩子在Y世代出生,因此层次深度不能确定姓名。
+----+----------+-----------+------------+--------+
| ID | Name | Parent_ID | Generation | Gender |
+----+----------+-----------+------------+--------+
| 1 | John | NULL | X | Male |
| 2 | Jill | 1 | Y | Female |
| 3 | Andy | 2 | Z | Male |
| 4 | Ralph | 2 | Z | Male |
| 5 | Lisa | NULL | X | Female |
| 6 | Steve | 5 | Y | Male |
| 7 | Sean | 6 | Y | Male |
| 8 | Sarah | 6 | Y | Female |
| 9 | Emily | 7 | Z | Female |
| 10 | Matt | 7 | Z | Male |
+----+----------+-----------+------------+--------+
所需的输出:(如果SET @GenX = 'Lisa';
)
+-------+
| Name |
+-------+
| Emily |
| Matt |
+-------+
到目前为止,这是我的代码。
SET @GenX = 'Lisa';
SELECT t2.name AS Kids
FROM (SELECT name, Parent_ID
FROM FamilyTree
WHERE Gender = 'Male' OR Gender = 'Female') t1
LEFT JOIN FamilyTree t2 ON t2.ID = t1.Parent_ID
LEFT JOIN FamilyTree t3 ON t3.ID = t2.Parent_ID
LEFT JOIN FamilyTree t4 ON t4.ID = t3.Parent_ID
WHERE t3.name = '@GenX' OR t4.name - '@GenX'
GROUP BY t2.name
HAVING SUM(t1.Gender) > 0 AND SUM(t1.Gender) > 0;
这将返回正确的父名称,但不会返回子名称。如果我SELECT
和GROUP BY
孩子的名字,我找不到哪个孩子有姐妹/兄弟。谢谢您的帮助。我真的坚持这个。
您可以假设没有重复的名称或重叠的家族树。
答案 0 :(得分:0)
;with cte
as
(
Select id,name,Parent_id,generation,gender from family_tree where name =@name and generation='x'
Union All
Select t.id, t.name,t.Parent_id,t.generation,t.gender from family_tree t
join cte c on c. id=t.parent_id
)
,condition
as
(
select Parent_id,COUNT(*) cnt from cte Where generation='z' Group by parent_id having COUNT(*)>1
)
,sibling
as
(
select parent_id,Count(gender) cntg from
(select distinct c.parent_id,c.gender from cte c join condition co on co.parent_id=c.parent_id) a
group by parent_id having count(gender)>1
)
select c.name from cte c join sibling s on c.parent_id=s.parent_id
答案 1 :(得分:0)
假设您只有3代,您可以使用以下查询
SELECT NAME FROM FamilyTree WHERE PARENT_ID IN
(SELECT ID FROM FamilyTree WHERE PARENT_ID IN
(SELECT ID FROM FamilyTree WHERE PARENT_ID =
(SELECT ID FROM FamilyTree WHERE NAME = 'Lisa')
)
) AND
(SELECT COUNT(ID) FROM
(SELECT ID FROM FamilyTree WHERE PARENT_ID IN
(SELECT ID FROM FamilyTree WHERE PARENT_ID IN
(SELECT ID FROM FamilyTree WHERE PARENT_ID =
(SELECT ID FROM FamilyTree WHERE NAME = 'Lisa')
)
)
)T2
)=2 AND GENARATION = 'Z'
如果只有3代,上面的查询将给出结果 如果它更多,你必须添加更多的内部查询,它会影响你的表现。
答案 2 :(得分:0)
我最初的尝试返回了兄弟/姐妹Generation Z孩子的每个父母的id(姓名)。使用IN
运算符将子项的名称与第一个嵌套SELECT
语句中给出的父ID相关联所需的解决方案。
SET @GenX = 'Lisa';
SELECT name FROM FamilyTree WHERE Parent_ID IN
(SELECT t2.id AS Kids
FROM
(SELECT name, Parent_ID
FROM FamilyTree
WHERE Gender = 'Male' OR Gender = 'Female') t1
-- Iterate through hierarchy
LEFT JOIN FamilyTree t2 ON t2.ID = t1.Parent_ID
LEFT JOIN FamilyTree t3 ON t3.ID = t2.Parent_ID
LEFT JOIN FamilyTree t4 ON t4.ID = t3.Parent_ID
WHERE t3.name = '@GenX' OR t4.name - '@GenX'
GROUP BY t2.id
HAVING SUM(t1.Gender) > 0 AND SUM(t1.Gender) > 0); -- includes only brother/sister siblings