mySql - 查找所有不是用户的 friend

标签 mysql

我正在创建一个社交网络,我正在尝试编写一个 mySql 查询来查找不是特定用户 friend 的所有用户。 有一张表 - USERS,其中包含 id_user、姓名和电子邮件。

USERS:
user_id , name , email..
1         Dan     a@a.com
2         Ron     b@b.com
3         James   c@c.com
4         Joe     d@d.com
5         Max     c@c.com

还有显示关系的 FRIENDS 表(status=2 表示两人是 friend ):

FRIENDS:
user_id , friend_id , status
1             2         2
3             1         2
4             3         2 

提供不是 user_id =1 好友的 user_id(来自 USERS)列表的 mySql 查询是什么? (用户 4 和 5)。

最佳答案

反连接模式应该足够了。

看起来“a是b的 friend ”可以在 friend 表中用一行表示,(a,b,2)(b,a,2) 。 (这对我来说并不完全清楚,但我现在假设这是真的。)

此查询只是第一步。要在 friend 表中双向检查 friend ,我将在连接谓词中使用 OR 条件。

这本质上是从用户获取所有行,以及从 friend 获取“匹配”行。 “trick”是 WHERE 子句中的谓词,它消除了在 friend 中找到“匹配”的所有行,只留下 users 中没有找到“匹配”的行一场“比赛”。

SELECT u.user_id
     , u.name
  FROM users u
  LEFT
  JOIN friends f
    ON ( f.user_id   = u.user_id AND f.friend_id = ? AND f.status = 2 )
    OR ( f.friend_id = u.user_id AND f.user_id   = ? AND f.status = 2 )
 WHERE f.user_id   IS NULL
    OR f.friend_id IS NULL

不幸的是,MySQL 优化器通常不会太优雅地处理这些 OR 条件。作为重写的另一个切入点,我们可以尝试将与 friend 的连接分成两个左连接。

我认为这是等效的:

SELECT u.user_id
     , u.name
  FROM users u
  LEFT
  JOIN friends f
    ON ( f.user_id   = u.user_id AND f.friend_id = ? AND f.status = 2 )
  LEFT
  JOIN friends g
    OR ( g.friend_id = u.user_id AND g.user_id   = ? AND g.status = 2 )
 WHERE f.user_id   IS NULL 
   AND g.friend_id IS NULL

(我还没有测试第二个查询...目标是做同样的事情。来自 users 的所有行,以及来自 friends 的匹配行,然后过滤掉所有具有匹配的行。

编辑

我认为我们还需要从“特定用户的”用户中过滤掉行。上面的查询将返回用户自己作为他自己的“不是 friend ”。为此,我们可以添加到 WHERE 子句

 AND u.user_id <> ?

对于第一个查询,我们需要注意 ORAND bool 运算符之间的优先顺序...我认为我们需要换行第一个查询中括号中的两个“或”条件。

<小时/>

跟进

还有一些其他查询模式可以返回等效结果。作为两个示例,我们可以使用 NOT IN(子查询) 形式的谓词,或 NOT EXISTS(子查询) 形式的谓词。

使用“NOT IN(子查询)”

使用这种形式时,请注意子查询不会返回 NULL 值。如果列表中有 NULL 值,则谓词将不会返回 TRUE。

SELECT u.user_id
     , u.name
  FROM users u
 WHERE u.user_id NOT IN ( SELECT f.user_id
                            FROM friends f
                           WHERE f.user_id IS NOT NULL
                             AND f.status = 2
                             AND f.friend_id = ?
                        )
   AND u.user_id NOT IN ( SELECT f.friend_id
                            FROM friends f
                           WHERE f.friend_id IS NOT NULL
                             AND f.status = 2
                             AND f.user_id = ?
                        )
   AND u.user_id <> ?

使用“NOT EXISTS(子查询)”

SELECT u.user_id
     , u.name
  FROM users u
 WHERE NOT EXISTS ( SELECT 1 
                      FROM friends f
                     WHERE f.user_id = u.user_id
                       AND f.status = 2
                       AND f.friend_id = ?
                  )
   AND NOT EXISTS ( SELECT 1
                      FROM friends g
                     WHERE g.friend_id = u.user_id
                       AND g.status = 2
                       AND g.user_id = ?
                  )
   AND u.user_id <> ?

关于mySql - 查找所有不是用户的 friend ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30115727/

相关文章:

mysql - 与同一列中的多个值进行比较?

php - 无法获取包含所有查询结果的表

php - 在 mysql 中检查所选日期和当前日期的差异

php - 特殊字符无法插入数据库

MySQL 分组如果表中不存在则强制返回空值

php - Woocommerce 中某些产品的批量更新费用

mysql - 从表中删除多行 (SQL)

mysql - Rails MySQL 连接问题

java.sql.Types.JSON 不是默认的 JDBC 类型

mysql - 随机 "Lost connection to MySQL server at '读取初始通信包',系统错误: 110"