2017-11-10 151 views
3

我完全能夠得到所有的登錄用戶當前的朋友,這是我此查詢這裏做 -如何獲取登錄用戶不是MySQL中的所有用戶?

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

但我想要做的相反,我也搞不清楚。

我想要做朋友的邏輯。

我需要得到所有誰是當前登錄用戶的用戶尚未朋友

我有一個用戶表和朋友表作爲一個多用戶和他們的朋友之間一對多的關係。 friends表中的鍵是user_id friend_id。

爲了說明某人是我與其他用戶的朋友(說登錄的用戶ID是3,朋友的用戶ID是6)user_id = 3friend_id = 6作爲一行,然後把另一行與ID的翻轉來說明友誼的另一種方式,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  | 
|---------------------|------------------|------------------| 

編輯:

我想我已經縮小我的問題有點更簡潔。

我想從用戶表中獲取所有用戶,其中他們的ID不會顯示爲朋友表中當前登錄用戶的user_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限制爲沒有行是朋友的組。

1

對於更大的數據集,我會用一個NOT 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(反)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 IN子查詢,如果用戶預計將有很多的朋友更好的性能。如果不是在子查詢執行相同,如果不是更好。

請注意DISTINCT。你需要這個,因爲這種關係是多對多的。