在单个MySQL查询中选择父,子,孩子等

时间:2012-10-26 05:29:50

标签: mysql relationship

我觉得这一定是个经典问题,但我找不到答案。

我有一个表人物,其中包含描述一个人的基本细节。然后,我有一个ParentChildRelationship表,看起来像这样:

CREATE TABLE `ParentChildRelationship` (
    `ParentId` INT(10) UNSIGNED NOT NULL,
    `ChildId` INT(10) UNSIGNED NOT NULL,
 PRIMARY KEY(ParentId,ChildId),
 CONSTRAINT `FK_ParentRelationship`
    FOREIGN KEY (`ParentId` )
    REFERENCES `Person` (`idPerson` ),
 CONSTRAINT `FK_ChildRelationship`
    FOREIGN KEY (`ChildId` )
    REFERENCES `Person` (`idPerson` )
);

我需要一个select查询,它只返回Parent的所有Person记录和树下的所有Children。

例如,使用以下数据:

Parent   Child
1        3
1        8
2        4
3        5
3        6
6        9
4        7

选择ParentId = 1或ChildId位于树下面 ParentId为1的所有Person记录。此查询应返回Person信息(SELECT * FROM Person ...)对于以下PersonId:

1,3,8,5,6,9

我不知道这是否重要,但这些返回的顺序并不重要,因为我需要根据“LastName”之类的东西进行订购。换句话说,结果也可能是1,3,5,6,9,8。

3 个答案:

答案 0 :(得分:3)

如果您具有已知的有限深度,则可以展开递归并使用存储过程或视图。对于MySQL,以下工作:

存储常规解决方案:

DELIMITER $$ 

CREATE PROCEDURE GetRelatedPersonsWithPersonId( IN pId VARCHAR(36)) 
        BEGIN 
                select * from Person where idPerson in ( 
                        select ParentId from ParentChildRelationship where ParentId = pId 
                        union 
                        select ChildID from ParentChildRelationship where ParentId = pId 
                        union 
                        select ChildID from ParentChildRelationship where ParentId in (select ChildID from ParentChildRelationship where ParentId = pId) 
                        union 
                        select ChildID from ParentChildRelationship where ParentId in (select ChildID from ParentChildRelationship where ParentId in (select ChildID from ParentChildRelationship where ParentId = pId)) 
                ) ; 

        END $$ 

查看解决方案:

Create view ChildRecurse 
As 
Select ParentId, ChildID from ParentChildRelationship 
Union 
Select x1.ParentId, x2.ChildId from ParentChildRelationship x1 
               Inner join ParentChildRelationship x2 on x2.ParentId = x1.ChildId 
Union 
Select x1.ParentId, x3.ChildId from ParentChildRelationship x1 
               Inner join ParentChildRelationship x2 on x2.ParentId = x1.ChildId 
               Inner join ParentChildRelationship x3 on x3.ParentId = x2.ChildId 
Union 
Select x1.ParentId, x4.ChildId from ParentChildRelationship x1 
               Inner join ParentChildRelationship x2 on x2.ParentId = x1.ChildId 
               Inner join ParentChildRelationship x3 on x3.ParentId = x2.ChildId 
               Inner join ParentChildRelationship x4 on x4.ParentId = x3.ChildId 

然后选择:

select * from person where idPerson=@ID or idPerson in (select ChildId from ChildRecurse where ParentId=@ID) 

答案 1 :(得分:1)

您的数据模型称为adjacency list model。您无法使用该模型执行查询(尽管存储过程可以)。

解决此问题的常用方法是更改​​为nested set model。维基百科的文章有一些示例代码,并且有一个很好的教程here(以及对使用邻接列表模型所涉及内容的一个很好的描述)。

答案 2 :(得分:0)

我认为这将是GROUP BY和HAVING声明的工作。

这样的事情是否指向正确的方向?

SELECT * FROM ParentChildRelationship pcr
GROUP BY ParentID , ChildID
HAVING ParentID=1 OR Count(ChildID)>0 

这将为您提供一个父子关系列表,您可以通过INNER JOIN将其加入到person表中。

相关问题