🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

4回答

763閲覧

SQLで友達の友達を取得

Chandler_Bing

総合スコア673

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

2クリップ

投稿2019/09/09 07:29

編集2019/09/09 23:26

ユーザーテーブル

ID NAME
1 ヤマダ
2 Chandler
3 Monica
4 Joey

友達申請テーブル
FROM TO
1    2
2    3
4    1

【修正】

のような2つのテーブルがあるとします。
この二つを使って友達の友達を取得する方法を教えていただきたいです。

今回の場合だと1は2,4と友達で
2(1の友達)は3と友達関係にあります。

さらに1と3は友達ではありません。この値がほしいです。

この友達申請に入っているレコードは友達関係にあります。(申請中や、却下はありません)
またこの問題として友達関係になるには、TOでもFROMのどちらからでも可能です。(1と2、4と1)

友達申請にユーザーをLEFT JOINJで2つ結合しました。
この段階で、自分(1)の友人は把握できますが、ここからどうやって友達の友達を取得できますか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/09/09 07:36 編集

がんばればできます。 アドバイスを求めるのであればまともな質問にしてください。 「質問テンプレート」を利用し「質問するときのヒント」を熟読して質問を再編してください。 https://teratail.com/help/question-tips 196も質問してきておいてこの質問の仕方はどうなんでしょう。
yambejp

2019/09/09 07:33

> さらに1と3は友達ではありません 2行前で友達って言ってますが・・・
hihijiji

2019/09/09 07:58

相互友達申請があった場合に友達関係とみなすのがいいと思います。
Orlofsky

2019/09/09 08:04

>2行前で友達って言ってますが・・・ 片思い、ってヤツでしょう。
Zuishin

2019/09/09 23:56 編集

テーブルが大きくなると友達の友達候補は膨大な人数になると思いますので、それを一つの select で取得しようとすると時間がかかりそうです。 友達の友達テーブルを作り、友達申請や破棄が一件あるたびに更新する方が良いのではないかと思います。それなら多少時間がかかってもユーザーには「更新には時間がかかる可能性があります」と伝えておけば済みます。
guest

回答4

0

ここからどうやって友達の友達を取得できますか。

もう一度友達申請テーブルをJOINします。
1回目でとれるのが自分と友達のID
2回目に1回目の友達のID(TO)をFROMに結合してあげたらそのTOが友達の友達になります。

FROM 1TO 1FROM 2TO 2
1223
23nullnull
4112

これにそれぞれのIDに対応するNAMEをわりあててあげれば友達の友達の名前が取れます。

SQL

1SELECT 2 u.NAME, 3 f2u.NAME 4FROM 5 ユーザーテーブル u 6INNER JOIN 7 友達申請テーブル f1 8ON 9 u.ID = f.FROM 10INNER JOIN 11 友達申請テーブル f2 12ON 13 f.TO= ff.FROM 14INNER JOIN 15 ユーザーテーブル f2u 16ON 17 ff.TO = f2u.ID

INNER JOINにしているのは友達や友達の友達がいないレコードを省くためです。

注意:このSQLでは1は2の友達ですが2は1の友達ではありません。そこを考慮するともう少し複雑なSQLになります。

投稿2019/09/10 14:06

shirokuma4690

総合スコア154

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

ユーザーをLEFT JOINで2つ結合しました。

⇒実際のSQLを記載して欲しかったですね。
色々な結合方法があるので、この文章だけではどういうJOINか分かりません。

とりあえず、FROM-TOが相互と言うことなので、
私の方からは、友達テーブル作る方法で。

友達テーブル
FROM TO
1    2
2    3
4    1
2    1 ←FROM TOの逆を追加
3    2 ←FROM TOの逆を追加
1    4 ←FROM TOの逆を追加

SQL

1SELECT T1.ID 2 , T3.FROM 3FROM ユーザーテーブル T1 4 LEFT JOIN 友達テーブル T2 ON( 5 T2.FROM = T1.ID 6 ) 7 LEFT JOIN 友達テーブル T3 ON( 8 T3.FROM = T2.TO 9 ) 10WHERE NOT EXISTS( 11 SELECT 'X' 12 FROM 友達テーブル T4 13 WHERE T4.TO = T1.ID 14 AND T4.FROM = T3.FROM 15 )

どうしても、友達申請テーブルで表現したい場合、
UNION ALL等を使って、
↑のような抽出結果になる友達ビューを作成して、上記SQLにするとかですね。

投稿2019/09/30 21:11

tomari_perform

総合スコア760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

FROM と TO の両方向があるので面倒になっているので、共通テーブルなどを使って単方向にしてみてはどうでしょうか?

SQL

1WITH W_F AS ( 2 SELECT [FROM] F, [TO] T FROM 友達申請テーブル 3 UNION ALL 4 SELECT [TO] F, [FROM] T FROM 友達申請テーブル 5) 6SELECT DISTINCT U.*, F2.T 7FROM ユーザーテーブル U 8LEFT JOIN W_F F1 ON F1.F = U.ID 9LEFT JOIN W_F F2 ON F2.F = F1.T 10WHERE U.ID <> F2.T

投稿2019/09/10 04:19

編集2019/09/10 04:21
x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ちょっとヒントになれば。

テーブル設計を
友達になるように申請した人、友達リクエストを受けた人、ステータス(友達申請中、友達成立、友達拒否) で変えて考えてみては?

投稿2019/09/09 08:05

Orlofsky

総合スコア16417

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chandler_Bing

2019/09/09 08:22

つまりStatusを増やすということでししょうか。 非現実的的ですが、今回は申請があれば友達としていますので、 Statusはロジックに影響を与えないともうのですが。
yambejp

2019/09/09 08:51

補足にも書きましたが、どういう場合が友達でどういう場合が友達じゃないのかはっきりさせてください
Orlofsky

2019/09/09 08:57

難しいことを後回しにして砂上の楼閣になることは多々あります。 間違ったルールを作ってしまうことは世界中どこでもあることですが、ほどんどの国ではルールが現実にそぐわないとわかるとそのルールを修正します。一度決めた事はどんなに間違ったことであろうと、絶対に変えないのは日本の絶望的な特性です。
shirokuma4690

2019/09/09 21:26

友達申請テーブルの FROM TO 1    3 のレコードは1と3が友達だからあるんですか?それとも友達の友達だからあるんですか? ここが一番の混乱の元だと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問