2017-11-10 150 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。你需要这个,因为这种关系是多对多的。