页面推荐:朋友喜欢、而我还没喜欢的页面
LeetCode 1264 · 双向关系、IN / NOT IN、去重
面试怎么回答
朋友关系是无向的,所以用 CASE WHEN user1_id = 1 THEN user2_id ELSE user1_id END 在两种存储方向里都取出朋友;再取朋友喜欢的页面,NOT IN 排除 1 号已喜欢的,DISTINCT 去重。存储方向不固定的关系,都要先「对称化」再用。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
好友表每行是一对好友(顺序不固定),喜欢表记录用户喜欢的页面。给 1 号用户推荐他的朋友们喜欢、但他自己还没喜欢的页面,不要重复。
表结构
- Friendship:user1_id、user2_id;(user1_id, user2_id) 为主键
- Likes:user_id、page_id;(user_id, page_id) 为主键
思路
先找出 1 号用户的所有朋友:好友关系可能存成 (1, x) 也可能存成 (x, 1),两种都要取另一端。再取这些朋友喜欢的页面,排除 1 号自己已经喜欢的,最后去重。
参考解法
select distinct page_id recommended_page
from Likes
where user_id in(
select if(user1_id=1,user2_id,user1_id) user_id
from Friendship
where user1_id =1 or user2_id =1
)
and page_id not in (select page_id from Likes where user_id=1)
易错点
- 只查 user1_id = 1 会漏掉存成 (x, 1) 的好友。
- NOT IN 的子查询理论上要防 NULL,这里 page_id 是主键的一部分不会为空。