0

在此处输入图像描述

嗨,我有这两个表:用户和朋友(friend_status = 1 表示请求已发送,friend_status = 2 表示他们是朋友)。现在我想选择所有用户不是特定用户的朋友。怎么做?

假设当前用户是 1。我试过这个 SQL。它有效,但它太长而且太慢。第一个选择向 user1 发送请求但未被接受的所有用户。第二个选择从 user1 接收请求的所有用户。第三个和第四个选择所有不在“朋友”表中的用户。

SELECT user_id, name, email
                FROM
                (
                    SELECT user_id, name, email
                    FROM users u INNER JOIN friends f ON u.user_id = f.sender
                    WHERE f.receiver = 1 AND friend_status <> 2
                    UNION
                    SELECT user_id, name, email
                    FROM users u INNER JOIN friends f ON u.user_id = f.receiver
                    WHERE f.sender = 1 AND friend_status <> 2
            UNION
            SELECT u.user_id, u.name, u.email
                    FROM users u LEFT JOIN friends f ON u.user_id = f.sender
                    WHERE f.receiver IS NULL
                    GROUP BY user_id
                UNION 
            SELECT u.user_id, u.name, u.email
                    FROM users u LEFT JOIN friends f ON u.user_id = f.receiver
                    WHERE f.sender IS NULL
                    GROUP BY user_id
                ) T
        GROUP BY user_id

更新:添加图片。 在此处输入图像描述

4

4 回答 4

2
SELECT
    a.user_id,
    a.name,
    a.email,
    b.status IS NOT NULL AS friend_status
FROM
    users a
LEFT JOIN
    friends b ON 
        a.user_id IN (b.sender, b.receiver) AND
        1 IN (b.sender, b.receiver)
WHERE
    (b.friend_id IS NULL OR b.status <> 2) AND
    a.user_id <> 1

您之前在这里问过一个问题- “选择与任何人都不是朋友的用户”,我提供了一个使用LEFT JOIN.

在此基础上,要选择与特定用户不是朋友的用户,我们只需将该特定用户的 ID 添加到LEFT JOIN条件 ( 1 IN (b.sender, b.receiver) 中。

次要编辑:除非用户可以与他/她自己成为朋友,否则选择我们正在选择的用户是没有意义的!所以我加了WHERE a.user_id <> 1

于 2012-06-25T07:41:38.240 回答
1

您可以通过使用以下内容来简化此操作:

SELECT user_id, name, email
FROM
(
    SELECT u.user_id, u.name, u.email
    FROM users u LEFT JOIN friends f ON u.user_id = f.sender
    WHERE IFNULL(friend_status,0) <> 2
    GROUP BY user_id
    UNION
    SELECT u.user_id, u.name, u.email
    FROM users u LEFT JOIN friends f ON u.user_id = f.receiver
    WHERE IFNULL(friend_status,0) <> 2
    GROUP BY user_id
) T
GROUP BY user_id

IFNULL 函数返回第一个参数的值,将 NULL 替换为 value 第二个参数的值。在这种情况下,这意味着如果朋友表中没有匹配的朋友,friend_status 将被视为 0,这使您可以将 UNION 中的选择次数减少一半。

于 2012-06-25T07:13:42.293 回答
1

假设您要在user_id1 上执行查询:

SELECT user_id, name, email
FROM users AS u
WHERE NOT EXISTS (SELECT * FROM friends AS f
                  WHERE (f.sender = u.user_id AND f.receiver = 1 AND f.friend_status = 2)
                  OR (f.sender = 1 AND f.receiver = u.user_id AND f.friend_status = 2)
                 )
AND u.user_id <> 1

子查询获取所有已建立的友谊关系,其中用户 1 是发送者或接收者。外部查询选择不存在此类关系的所有用户。ID 为 1 的用户被排除在使用最后一行的查询之外,因为即使他不能与自己成为朋友,我想他也不应该出现在最终的查询结果中。

于 2012-06-25T07:15:59.080 回答
1

试试这个查询

select
  u.user_id,
  u.name,
  u.email,
  ifnull(f.friend_status,0) as Relation
from users as u
  left join friends as f
    on f.sender = u.user_id
where u.user_id not in(select
             sender
               from friends
               where sender = 1)

这里 sender = 1 表示用户 id = 1。您可以传递用户 id 来限制此条件。状态 0 也意味着他不是朋友。和 1 , 2 , 3 是根据你的规则

于 2012-06-25T07:40:57.390 回答