我正在创建一个社交网络,我正在尝试编写一个 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 <> ?
对于第一个查询,我们需要注意 OR
和 AND
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/