MySQL高阶1949-坚定地友谊
目录
题目
准备数据
分析数据
实现
题目
如果 x
和 y
为 朋友 且他们 至少 有三个共同的朋友 ,那么 x
和 y
之间的友谊就是 坚定的。
写一个解决方案来找到所有的 坚定的友谊。
注意,结果表不应该包含重复的行,并且 user1_id < user2_id
。
以 任何顺序 返回结果表。
准备数据
Create table If Not Exists Friendship (user1_id int, user2_id int)
Truncate table Friendship
insert into Friendship (user1_id, user2_id) values ('1', '2')
insert into Friendship (user1_id, user2_id) values ('1', '3')
insert into Friendship (user1_id, user2_id) values ('2', '3')
insert into Friendship (user1_id, user2_id) values ('1', '4')
insert into Friendship (user1_id, user2_id) values ('2', '4')
insert into Friendship (user1_id, user2_id) values ('1', '5')
insert into Friendship (user1_id, user2_id) values ('2', '5')
insert into Friendship (user1_id, user2_id) values ('1', '7')
insert into Friendship (user1_id, user2_id) values ('3', '7')
insert into Friendship (user1_id, user2_id) values ('1', '6')
insert into Friendship (user1_id, user2_id) values ('3', '6')
insert into Friendship (user1_id, user2_id) values ('2', '6')
分析数据
第一步:
用
UNION ALL
合并,UNION ALL
不会消除重复的行,意味着如果user1_id
和user2_id
互为好友,那么这两行都会被包含。并且按照user_id
和friend_id
的顺序。select user1_id user_id,user2_id friend_id from Friendship union all select user2_id,user1_id from Friendship order by 1,2;
第二步:
where (t1.user_id, t2.user_id) in (select * from t)
:确保t1
和t2
中的user_id
对在CTEt
中存在。and t1.friend_id = t2.friend_id
:确保t1
和t2
有相同的friend_id
,即它们有共同的好友。and t1.user_id < t2.user_id
:确保user1_id
小于user2_id
,避免重复的组合(例如,用户1和用户2与用户2和用户1被视为相同的组合)。group by 1, 2
:按user1_id
和user2_id
分组。having count(distinct t1.friend_id) >= 3
:筛选出至少有3个不同共同好友的用户对。with t as ( (select user1_id user_id,user2_id friend_id from Friendship union all select user2_id,user1_id from Friendship) order by 1,2 ) select * from t t1,t t2 where (t1.user_id,t2.user_id) in (select * from t) and t1.friend_id = t2.friend_id and t1.user_id < t2.user_id order by 1,2;
第三步:
select t1.user_id user1_id, t2.user_id user2_id, count(distinct t1.friend_id) common_friend
:选择两列user1_id
和user2_id
,以及它们之间不同的共同好友数量common_friend
。with t as ( (select user1_id user_id,user2_id friend_id from Friendship union all select user2_id,user1_id from Friendship) order by 1,2 ) select t1.user_id user1_id ,t2.user_id user2_id ,count(distinct t1.friend_id) common_friend from t t1,t t2 where (t1.user_id,t2.user_id) in (select * from t) and t1.friend_id = t2.friend_id and t1.user_id < t2.user_id group by 1,2 having count(distinct t1.friend_id) >=3;
实现
with t as (
(select user1_id user_id,user2_id friend_id
from Friendship
union all
select user2_id,user1_id
from Friendship)
order by 1,2
)
select t1.user_id user1_id
,t2.user_id user2_id
,count(distinct t1.friend_id) common_friend
from t t1,t t2
where
(t1.user_id,t2.user_id) in (select * from t)
and t1.friend_id = t2.friend_id
and t1.user_id < t2.user_id
group by 1,2
having count(distinct t1.friend_id) >=3;