我觉得这一定是个经典问题,但我找不到答案。
我有一个表人物,其中包含描述一个人的基本细节。然后,我有一个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。
答案 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表中。