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我只能(4)添加 1 个用户:

$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 null。如果您想根据select 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

编辑:

这个怎么样:(在 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


解决此问题的另一种方法(但可能不是最佳解决方案):

如果用户拥有的朋友数少于系统中的用户总数,则与两个表之间的完全联接相比,下面的联合查询可能不是一个昂贵的查询。

也不要忘记在表的列上uid添加fid索引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 回答
1

NOT IN您可以尝试JOIN使用表,而不是使用子查询friends

JOIN编辑了两次。一次在哪里1user_id一次在1哪里friend_id。然后我得到了所有不是朋友的1用户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

您的 SQL 查询正在做的是:获取 id 不等于 ANY friend_id 的所有用户,而不是当前用户(我假设)。

您想要的是检查朋友表中的朋友 ID 和用户 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 回答
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 回答