繁体   English   中英

相互的朋友sql

[英]Mutual friends sql

我在共同的朋友身上看到了多个SO帖子,但我在我的数据库中构建了我的朋友表,以便没有重复项,例如(1,2)而不是(2,1)

    Create Table Friends(
      user1_id int, 
      user2_id int
    );

然后是一个约束,以确保user1 id始终小于user2 id,例如4 <5

互助的朋友sql(Mysql)

我看到建议找到共同的朋友可以使用连接找到它,所以这就是我所拥有的,但我认为这是错误的,因为如果我用我的数据库中的数据计算查询的实际结果,我会得到不同的结果

select f1.user1_id as user1, f2.user1_id as user2, count(f1.user2_id) as 
mutual_count from Friends f1 JOIN Friends f2 ON 
f1.user2_id = f2.user2_id AND f1.user1_id <> f2.user1_id  GROUP BY
f1.user1_id, f2.user1_id order by mutual_count desc

我可以看到有三种连接方案。

1 -> 2 -> 3    (mutual friend id between other IDs)    
2 -> 3 -> 1    (mutual friend id > other IDs)    
2 -> 1 -> 3    (mutual friend id < other IDs)    

可以用这个谓词来解决......

ON f1.user1_id IN (f2.user1_id, f2.user2_id)
OR f1.user2_id IN (f2.user1_id, f2.user2_id)
AND <not joining the row to Itself>

但这将完全搞乱优化者使用索引的能力。

所以,我会结合多个查询。

(伪代码,因为我正在打电话)

SELECT u1, u2, COUNT(*) FROM
(
    SELECT f1.u1, f2.u2 FROM f1 INNER JOIN f2 ON f1.u2 = f2.u1 AND f1.u1 <> f2.u2
    UNION ALL
    SELECT f1.u1, f2.u1 FROM f1 INNER JOIN f2 ON f1.u2 = f2.u2 AND f1.u1 <> f2.u1
    UNION ALL
    SELECT f1.u2, f2.u2 FROM f1 INNER JOIN f2 ON f1.u1 = f2.u1 AND f1.u2 <> f2.u2
) all_combinations
GROUP BY u1, u2

然后,每个单独的查询将能够充分利用索引。 (在u1上放置一个索引,在u2上放置另一个索引)

结果应该是更少的深奥代码(具有相当长的CASE语句)和更低成本的执行计划。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM