1

2列のテーブルがありますusersIDsiblingID

特定のユーザーのすべての兄弟を見つけるための最良の方法は何ですか?

問題は複雑です。これが例です。

ユーザー1には5人の兄弟がいます(2,3,4,5,6)

テーブルはこんな感じ

userID|siblingID
1     | 2
1     | 3
6     | 5
5     | 3
3     | 1
4     | 6
4

4 に答える 4

3

ANSI SQL:

with recursive tree (userid, siblingid) as
(
   select userid, 
          siblingid
   from users
   where userId = 1
   union all 
   select c.userid,
          c.siblingid
   from users c
     join tree p on p.userid c.siblingId
)
select *
from tree;

Oracle11.2およびSQLServer(ANSI仕様を詳しく調べていなかったようです)の場合、recursiveキーワードを削除する必要があります(標準では必須です)。

于 2013-01-10T20:46:25.317 に答える
1

答えは、複数のSQLステートメントを使用したとしても、私が思っていたよりもはるかに困難でした。

あなたの質問に対する簡単な答えは、すべての兄弟関係を持つテーブルを作成することです。次に、これを次のようにクエリできます。

select siblingid
from @allsiblings sa
where sa.userid = 3   

1つのメモ。SQL Serverの構文を使用しているのは、それがたまたま最も便利なデータベースだからです。私はMySQLの機能のみを使用しているので、簡単に翻訳できるはずです。

テーブル@AllSiblingsを作成する方法は?さて、追加するものがなくなるまで、存在しない兄弟ペアを追加し続けてください。自己結合を行うことでペアを取得します。

コードは次のとおりです(前の警告が必要です)。

declare @allsiblings table (userid integer, siblingid integer);

declare @siblings table (userId int, siblingID int);

-- Initialize the @siblings table    
insert into @siblings(userId, siblingID)
    select 1 as userID, 2 as siblingID union all
    select 1 as userID, 3 as siblingID union all
    select 6 as userID, 5 as siblingID union all
    select 5 as userID, 3 as siblingID union all
    select 3 as userID, 1 as siblingID union all
    select 4 as userID, 6 as siblingID;

-- Initialize all siblings.  Note that both pairs are going in here    
insert into @allsiblings(userid, siblingid)
    select userId, siblingid from @siblings union
    select siblingID, userid from @siblings

-- select * from @allsiblings

while (1=1)
begin
    -- Add in new siblings, that don't exist by doing a self-join to traverse the links
    insert into @allsiblings
        select distinct sa.userid, sa2.siblingid
        from @allsiblings sa join
             @allsiblings sa2
             on sa.siblingid = sa2.userid
        where not exists (select * from @allsiblings sa3 where sa3.userid = sa.userid and sa3.siblingid = sa2.siblingid)

    -- If nothing was added, we are done        
    if (@@ROWCOUNT = 0) break;

    select * from @allsiblings;
end;    
于 2013-01-10T22:22:39.820 に答える
0

ループと一時テーブルを使用して再帰をシミュレートできます。最初に一時テーブルに開始ノードを挿入します。次に、一時テーブルに行がある間に、最初の行を取得し、一時テーブルから削除して、その場所にすべての兄弟を挿入します...

于 2013-01-10T20:38:14.540 に答える
0

http://sqlfiddle.com/#!4/0ef0c/5は、誰かが特定のエントリのすべての親戚を取得しなければならなかった例です。

対応するスタックオーバーフローの質問はここにあります: 階層クエリは子、親、兄弟をプルする必要があります

于 2013-01-10T20:41:14.160 に答える