2列のテーブルがありますusersID
。siblingID
特定のユーザーのすべての兄弟を見つけるための最良の方法は何ですか?
問題は複雑です。これが例です。
ユーザー1には5人の兄弟がいます(2,3,4,5,6)
テーブルはこんな感じ
userID|siblingID
1 | 2
1 | 3
6 | 5
5 | 3
3 | 1
4 | 6
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
キーワードを削除する必要があります(標準では必須です)。
答えは、複数の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;
ループと一時テーブルを使用して再帰をシミュレートできます。最初に一時テーブルに開始ノードを挿入します。次に、一時テーブルに行がある間に、最初の行を取得し、一時テーブルから削除して、その場所にすべての兄弟を挿入します...
http://sqlfiddle.com/#!4/0ef0c/5は、誰かが特定のエントリのすべての親戚を取得しなければならなかった例です。
対応するスタックオーバーフローの質問はここにあります: 階層クエリは子、親、兄弟をプルする必要があります