sql - 优化查找好友的查询
问题描述
我有一张代表成对人之间关系的表格。
user_relating | user_related | relation_type
--------------------------------------------
1 | 2 | 1 --> means user 1 follows user 2
我需要找到特定用户 X 的所有朋友。友谊意味着两个人互相关注。因此,如果用户 A 关注用户 B、C。并且用户 B、C 关注 A,则 B、C 是 A 的朋友。
我写了这个查询:
SELECT users.* -- user's followers
FROM users
JOIN user_relations rel
ON users.id = rel.user_relating AND user_related = 2
INTERSECT
SELECT users.* -- who the user follows
FROM users
JOIN user_relations rel
ON users.id = rel.user_related AND user_relating = 2;
但我认为这是低效的。有没有更优化的方法来完成这项工作?
我试过做这样的事情:
SELECT DISTINCT f.*
FROM users f
JOIN user_relations u1
on f.id = u1.user_related
JOIN user_relations u2
on f.id = u2.user_relating
WHERE u1.user_related = 2
or u2.user_related = 2;
通过 EXPLAIN ANALYZE 判断它似乎更有效(虽然我只有一个非常小的表,比如 10 行,所以我不确定这是一个很好的衡量标准)。
但这里的问题是它也会返回有问题的用户。意思是,如果我想要 User B 的朋友,那么这个查询会返回 User B 和他所有的朋友。我可以以某种方式从查询结果中排除用户 B 吗?
而且,如前所述,我很高兴收到一些关于执行此类查询的最优化和最有效方法的想法。
解决方案
可能最有效的方法是:
select ur.*
from user_relations ur
where ur.user_relating < ur.user_related and
ur.relation_type = 1 and
exists (select 1
from user_relations ur2
where ur2.user_relating = ur.user_related and
ur2.user_related = ur.user_relating and
ur2.relation_type = 1
);
并且为了性能,您需要在user_relations(user_relating, user_related, relationship_type)
.
也就是说,这与您的版本类似join
,但不需要删除重复项。
如果您有许多不同的关系类型,那么该列上的索引也会有所帮助。
编辑:
如果您有特定用户并想要他们的朋友:
select (case when user_relating = 2 then user_related else user_relating end) as user_friend
from user_relations ur
where ur.user_relating < ur.user_related and
ur.relation_type = 1 and
exists (select 1
from user_relations ur2
where ur2.user_relating = ur.user_related and
ur2.user_related = ur.user_relating and
ur2.relation_type = 1
) and
2 in (ur.user_relating, user_related)
推荐阅读
- tableau-api - 如何更改 Tableau 中计算字段列的单元格中的文本?
- amazon-web-services - AWS 使用用户名/密码登录还是社交登录?
- database - Azure AppService GitHub 存储库的数据库“主”中的 CREATE TABLE 权限被拒绝
- r - 为什么 fabletools::model() 这个合成数据会抛出错误?
- python - 如何使用 PySpark 和 Kafka 和 Spark Streaming 计算值的总和
- plugins - 在哪里可以看到 CDN 中 CKEditor 插件的完整列表?
- java - 配置 IntelliJ 以使用 Java 14 和记录
- laravel - 在 Laravel 中编写具有多个条件的查询
- pyspark - 谷歌 colab 中的 Py4JJavaError
- python - python编码和创建和SQlite