3

以下の表があります。

user
+-----------------------------------------------+
|  user_id    |  username   | Password | ...    |
+-----------------------------------------------+
|     1       |     a       |  ***     | ...    |
+-----------------------------------------------+
|     2       |     b       |  ***     | ...    |
+-----------------------------------------------+
|     3       |     c       |  ***     | ...    |
+-----------------------------------------------+
|     4       |     d       |  ***     | ...    |
+-----------------------------------------------+
|     5       |     e       |  ***     | ...    |
+-----------------------------------------------+

friends
+-----------------------------------------------+
|  f_id    |  user_id   | friend_id | ...       |
+-----------------------------------------------+
|     1    |     4      |  2        | ...       |
+-----------------------------------------------+
|     2    |     4      |  1        | ...       |
+-----------------------------------------------+
|     3    |     4      |  5        | ...       |
+-----------------------------------------------+
|     4    |     4      |  3        | ...       |
+-----------------------------------------------+

友達として追加できるすべてのユーザーを取得したい(この場合、のuser_id1はさらに3人の友達を追加する必要があります(2, 3, 5)。ただし、以下を使用すると、追加できるSQL statement belowユーザーは1人だけになります。(4)

$sql = "SELECT * FROM user WHERE user.user_id NOT IN 
(SELECT friends.friend_id FROM friends) AND 
user.user_id <> $_SESSION['id']." ORDER BY RAND() LIMIT 5";

しかし、これは、追加できるユーザーがいないユーザー4としてログインしたときにうまく機能します。これは私には少し注意が必要です。どんなアイデアでも大歓迎です。

ありがとう

4

6 に答える 6

2

これはどう?はnull、ユーザーがユーザーを友達として4追加してはならない場所を示しています。実際、。4でフィルターで除外できますAnd FID is not nullselect to be added friendsあなたがあなたのように特定のユーザーにしたいなら、session idあなたは別の条件でもそれを特定することができます:)

名前がユーザーではなく友達に表示されるように、別の結合を追加して更新しました。だけでなく、もう4存在しません。

クエリ:

select x.id, a.name, x.fid
from users a
join (
select u.id, u.name, f.fid
from users u
left join friends f
on u.id <> f.fid
and u.id <> f.uid) x
on x.fid = a.id
;

結果:

| ID | NAME | FID |
-------------------
|  1 |    b |   2 |
|  1 |    e |   5 |
|  1 |    c |   3 |
|  2 |    a |   1 |
|  2 |    e |   5 |
|  2 |    c |   3 |
|  3 |    b |   2 |
|  3 |    a |   1 |
|  3 |    e |   5 |
|  5 |    b |   2 |
|  5 |    a |   1 |
|  5 |    c |   3 |

特定のユーザーの場合、例:1

SQLFIDDLEデモユーザー1

select x.id, x.fid, a.name
from users a
join 
(select u.id, f.fid
from users u
inner join friends f
on u.id <> f.fid
and u.id <> f.uid
and u.id = 1)x
on x.fid = a.id
;

| ID | FID | NAME |
-------------------
|  1 |   2 |    b |
|  1 |   3 |    c |
|  1 |   5 |    e |
于 2013-01-22T17:29:41.113 に答える
1

SQLクエリが実行していることは次のとおりです。idがANYfriend_idと等しくなく、現在のユーザーではないすべてのユーザーを取得します(私は推測します)。

必要なのは、friendテーブルにfriend_idとuser_idのペアのレコードが存在しないことを確認することです。したがって、次のようになります。$ sql =

"SELECT * FROM user WHERE user.user_id NOT IN 
(SELECT friends.friend_id FROM friends WHERE friend.user_id = user.user_id) AND 
user.user_id <> $_SESSION['id']." ORDER BY RAND() LIMIT 5";
于 2013-01-22T17:26:30.863 に答える
1

NOT INサブクエリで使用する代わりにJOINfriendsテーブルを試すことができます。

JOIN二度編集しました。かつてはであり1user_idかつて1はであるfriend_id1次に、友達ではない、または友達であるすべてのユーザーを取得しました1

SELECT user.user_id,user.username

FROM user

LEFT JOIN friends AS fA ON fA.user_id = 1
LEFT JOIN friends AS fB ON fB.friend_id = 1

WHERE user.user_id != 1
AND NOT (user.user_id <=> fB.user_id)
AND NOT (user.user_id <=> fA.friend_id)

デモ:http ://sqlfiddle.com/#!2/1a7ae/30

于 2013-01-22T17:38:33.377 に答える
1

編集:

これはどうですか:(else句で無効なIDまたはログインしたユーザーと同じIDを使用します)

select * from users where id not in
(
   select (
            case
              when uid = 1 then id
              when fid = 1 then uid
             else 0
            end
          ) from friends where uid = 1 or fid = 1
) and id != 1 order by rand() limit 5;

http://sqlfiddle.com/#!2/12de1/62


これを解決するもう1つの方法(ただし、最適な解決策ではない可能性があります):

以下のユニオンクエリは、ユーザーの友達の数がシステム内のユーザーの総数より少ない場合、2つのテーブル間の完全な結合と比較してコストのかかるクエリではない可能性があります。

また、テーブルのインデックスuidfid列を追加することを忘れないでください。friends

select * from users where id not in 
(
     select id from friends where uid = 1
     union
     select uid from friends where fid = 1
) and id != 1 order by rand() limit 5;

http://sqlfiddle.com/#!2/12de1/40

于 2013-01-22T18:05:29.903 に答える
0

除外している現在のユーザーの友達に制限するためのサブクエリにwhere句がありません。

$sql = "select * from user u 
    where u.user_id not in 
    (select f.friend_id from friends f where f.user_id = ".$_SESSION['id'].")
    and u.user_id <> ".$_SESSION['id']." ORDER BY RAND() LIMIT 5";

また、これを行うために文字列連結を使用しないことをお勧めします。PDOの方が安全であり、SQLインジェクションのリスクはありません。

http://php.net/manual/en/ref.pdo-mysql.php

于 2013-01-22T17:25:36.927 に答える
0
SELECT u1.id u1_id
     , u2.id u2_id
  FROM users u1
  JOIN users u2
    ON u2.id <> u1.id
  LEFT
  JOIN friends f
    ON (f.fid = u1.id AND f.uid = u2.id)
    OR (f.fid = u2.id AND f.uid = u1.id)
 WHERE f.id IS NULL;
于 2013-01-22T18:04:04.380 に答える