2

これは古典的な問題に違いないと思いますが、答えが見つかりません。

私はテーブルPersonを持っています。このテーブルには、人を説明する基本的な詳細があります。次に、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` )
);

ツリーの下の親とすべての子のすべてのPersonレコードを返すだけのselectクエリが必要です。

たとえば、次のデータを使用します。

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

ParentId = 1またはChildIdが1のParentIdのPersonのツリーにあるすべてのPersonレコードを選択します。このクエリは、次のPersonIdのPerson情報(SELECT * FROM ...)を返す必要があります。

1,3,8,5,6,9

これが重要かどうかはわかりませんが、「LastName」などに基づいて注文する必要があるため、これらが返される順序は重要ではありません。つまり、結果は1,3,5,6,9,8である可能性もあります。

4

3 に答える 3

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) 
于 2012-10-26T19:12:50.653 に答える
1

データモデルは隣接リストモデルと呼ばれます。そのモデルで記述しているクエリを実行することはできません(ストアドプロシージャは実行できますが)。

これを解決する通常の方法は、入れ子集合モデルに変更することです。ウィキペディアの記事にはいくつかのサンプルコードがあり、ここにそれについての素晴らしいチュートリアルがあります(隣接リストモデルの使用に関係するものの良い説明とともに)。

于 2012-10-26T05:36:59.093 に答える
0

これは、GROUPBYおよびHAVINGステートメントの仕事になると思います。

このような何かがあなたを正しい方向に向けていますか?

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

これにより、INNERJOINを使用してpersonsテーブルに参加できる親子関係のリストが表示されます。

于 2012-10-26T05:40:29.683 に答える