2017-11-10 13 views
3

私は完全に私はここにこのクエリを実行するユーザーが現在ログインしている友人、の全てを取得することができています -ログインしたユーザーがMySQLで友達ではないすべてのユーザーを取得するにはどうすればよいですか?

SELECT users.* 
FROM users 
LEFT JOIN friends 
ON users.id = friends.friend_id 
WHERE friends.user_id = $user_logged_in_id 

をしかし、私は反対のことをやってみたい、と私はそれを把握することはできません。

私は友人ロジックをしようとしています。私は、ユーザーとその友人の間で多くの関係に多くのとして機能するように、ユーザテーブルや友人のテーブルを持っている

ですでに友人ではありません

私は現在ログインしているユーザーのすべてのユーザーを取得する必要があります。フレンドテーブルのキーは、user_id friend_idです。

誰かが私が置いた別のユーザーと友人であることを示すには(例えば、ログインしているユーザーIDは3、友人ユーザーIDは6)user_id = 3friend_id = 6を1行として表示し、他の方法で友情、user_id = 6friend_id = 3

ユーザーテーブル

|---------------------|------------------| 
|   id   |  username  | 
|---------------------|------------------| 
|   1   |  sonja12  | 
|---------------------|------------------| 
|   2   |  dorris32  | 
|---------------------|------------------| 
|   3   |  billy32  | 
|---------------------|------------------| 
|   4   |  micha97  | 
|---------------------|------------------| 
|   5   |  travis841 | 
|---------------------|------------------| 
|   6   |  johnny28  | 
|---------------------|------------------| 

友人テーブル

|---------------------|------------------|------------------| 
|   id   |  user_id  |  friend_id | 
|---------------------|------------------|------------------| 
|   1   |  3   |   6  | 
|---------------------|------------------|------------------| 
|   2   |  6   |   3  | 
|---------------------|------------------|------------------| 

EDIT:

私は私は私の質問もう少し簡潔にするために絞られていると思います。

ユーザーテーブルからすべてのユーザーを取得し、現在のログインしているユーザーのフレンドIDの横のフレンドIDがフレンドテーブルに表示されないようにしたいとします。

+1

より具体的には、今は '... WHERE friends.user_id!= $ user_logged_in_id" 'のように思われますが、これは修正されますが、うまくいきませんでしたか? – SourceOverflow

+0

いいえ、ログインしたユーザー以外のユーザーを返し、ユーザーを返しました ログインしたユーザーが友達ではないユーザーのリストを見たいので、簡単に「友達を追加」ボタンをクリックして新しい友達を追加することができます。すべてのユーザーを戻し、既にログインしているユーザーと友人であるものを除外しますが、普通のSQLがこのようなものに行くためにはるかに良い方法であるように感じます。 –

答えて

2

あなたは奇妙な方法で問題を考えています。これは、idが存在しない場合に存在する集合とは対照的に、作成する必要のある集合の集合として考えることを助けるかもしれません。

SELECT id from users WHERE id != $logged_in_user AND id NOT IN (SELECT friend_id from friends where user_id=$logged_in_user)

+1

注意: 'NOT IN(SELECT ...)'はひどくですMySQLで遅い –

+0

@RickJamesあなたはタスクを達成するために「NOT IN」よりも良い方法を知っていますか?私は間違いなくそれに気づいています。私は今ここでいくつかの答えを見ていますが、私はそれらをすべてテストすることができたと思う実行時間を記録してください。私の選択肢は以前リスト全体を返していて、各ユーザーのループ内で別のクエリを実行していたので、PHPの配列からそれらを取り除くために、私の選択肢はさらに遅くなりました8 \ –

+1

'NOT EXISTS(SELECT 1 ... ) ' - 答えが得られるまで評価し、リスト全体を構築しません。または、LEFT JOIN ... ON ... WHERE .. IS NULL' - 時には同様のコード。複合 'INDEX(user_id、friend_id)'はかなり助けになります。 –

0

SQL

SELECT u.* 
FROM usrs u 
LEFT JOIN friends f 
ON u.id = f.friend_id 
GROUP BY u.id, u.username, IF(f.user_id = $user_logged_in_id, 1, 0) 
HAVING MAX(IF(f.user_id = $user_logged_in_id, 1, 0)) = 0; 

デモ

http://rextester.com/ELXFZ39682

説明

クエリはオリジナルに基づいていますが、各ユーザーIDごとにグループ化されているため、重複は返されません。ログインしたユーザーの友人でないものを返すために、IF(f.user_id = $user_logged_in_id, 1, 0)は、その行がログインしているユーザーの友人であれば1に設定されたグループに生成された列を追加します。それ以外の場合は0を返します。 HAVING MAX(...) = 0は、いずれの行も友人でないグループに制限します。私は、NOTを使用することになり、より大きなデータセットの

1

は、サブクエリのクエリをEXISTS:

select u.* 
from users u 
where u.id <> $user_logged_in_id 
    and not exists (
    select * 
    from friends f 
    where f.user_id = $user_logged_in_id 
     and f.friend_id = u.id 
) 

またはLEFT(ANTI)のJOIN:

select u.* 
from users u 
left join friends f 
    on f.user_id = $user_logged_in_id 
    and f.friend_id = u.id 
where u.id <> $user_logged_in_id 
    and f.friend_id is null 

私は両方のクエリの実行プランがほとんどであるべきだと思います同じ。

デモ:http://rextester.com/KUOZ9198

0
SELECT DISTINCT users.id, users.username 
    FROM users 
     LEFT OUTER JOIN friends 
    ON (friends.user_id = $user_logged_in_id and friends.friend_id = users.id) 
WHERE users.id <> $user_logged_in_id 
    AND friends.friend_id is null; 

このクエリは、サブクエリで、ユーザーが友人の多くを持っていることが予想されていない場合よりもパフォーマンスである可能性が高いです。サブ問合せでNOTでない場合は、同じでない場合は同じを実行します。

DISTINCTに注意してください。この関係は多くのものか​​ら多くのものになるため、これが必要です。

関連する問題