SELECT列与层次结构中的GROUP BY列不同

时间:2017-01-05 02:40:43

标签: mysql sql hierarchical-data

我使用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;

这将返回正确的父名称,但不会返回子名称。如果我SELECTGROUP BY孩子的名字,我找不到哪个孩子有姐妹/兄弟。谢谢您的帮助。我真的坚持这个。

您可以假设没有重复的名称或重叠的家族树。

3 个答案:

答案 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