Php MySQL-不会产生不想要的结果

Php MySQL-不会产生不想要的结果,php,mysql,join,not-exists,notin,Php,Mysql,Join,Not Exists,Notin,我有以下表格: user +-----------------------------------------------+ | user_id | username | Password | ... | +-----------------------------------------------+ | 1 | a | *** | ... | +------------------------------------

我有以下表格:

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        | ...       |
+-----------------------------------------------+
我想将所有可用的用户添加为好友在这种情况下,用户_id为1将有3个以上的好友添加2、3、5。但是,通过使用下面的SQL语句,我只能添加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的身份登录时,这非常有效,因为没有可添加的用户。这对我来说有点棘手。任何想法都将不胜感激


谢谢

您在子查询中缺少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注入的风险


SQL查询所做的是:获取id不等于任何friend_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";
这个怎么样?null表示用户4不应将用户4添加为好友的位置。。事实上,您可以通过将其过滤掉,并且FID不为空。如果要根据会话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
;
对于特定用户,例如1

您可以尝试加入friends表,而不是在子查询中使用NOT IN

我参加了两次。其中1是用户id,1是朋友id。然后我得到了所有与1不是朋友或是1的用户

演示:

编辑:

这个怎么样: in 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;
解决此问题的另一种方法可能不是最佳解决方案:

若用户的好友数小于系统中的用户总数,则下面的联合查询与两个表之间的完全联接相比可能不是一个代价高昂的查询

另外,不要忘记在friends表的uid和fid列上添加索引


在嵌套查询中不需要WHERE子句吗?我也尝试过,但仍然不起作用。我尝试了WHERE friends.friends\u id$\u SESSION['id']或其他内容?否-WHERE friends.user\u id=$\u SESSION['id']-您想查找此用户尚未成为朋友的人,对吗?所以你想说不在说用户是朋友的人列表中。@tepkenvannkorn的问题+1,interesting@tepkenvannkorn请尝试一下并发表评论:我刚刚发布了一个类似的答案。这似乎比我的好!>>@RocketHazmat很高兴提醒大家注意到我在最后一个查询中给出了错误的链接:不必在第二个示例中使用子查询,只需再次加入users表即可获得用户名。OP可以检查解释计划并作出决定。我只是将这两个查询保留在原来的子查询方法中以保持一致性。第二个选项非常简单。谢谢@Manu的帮助
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 |
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)
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;
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;
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;