题目描述

(通过次数10,309 | 提交次数17,975,通过率57.35%)

朋友关系列表:Friendship
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| user1_id | int |
| user2_id | int |
+---------------+---------+
这张表的主键是 (user1_id, user2_id)。
这张表的每一行代表着 user1_id 和 user2_id 之间存在着朋友关系。
喜欢列表:Likes
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| user_id | int |
| page_id | int |
+-------------+---------+
这张表的主键是 (user_id, page_id)。
这张表的每一行代表着 user_id 喜欢 page_id。
写一段 SQL 向user_id = 1 的用户,推荐其朋友们喜欢的页面。不要推荐该用户已经喜欢的页面。
你返回的结果中不应当包含重复项。
返回结果的格式如下例所示。
示例 1:
输入:
Friendship table:
+----------+----------+
| user1_id | user2_id |
+----------+----------+
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 3 |
| 2 | 4 |
| 2 | 5 |
| 6 | 1 |
+----------+----------+
Likes table:
+---------+---------+
| user_id | page_id |
+---------+---------+
| 1 | 88 |
| 2 | 23 |
| 3 | 24 |
| 4 | 56 |
| 5 | 11 |
| 6 | 33 |
| 2 | 77 |
| 3 | 77 |
| 6 | 88 |
+---------+---------+
输出:
+------------------+
| recommended_page |
+------------------+
| 23 |
| 24 |
| 56 |
| 33 |
| 77 |
+------------------+
解释:
用户1 同 用户2, 3, 4, 6 是朋友关系。
推荐页面为:页面23 来自于 用户2, 页面24 来自于 用户3, 页面56 来自于 用户3 以及 页面33 来自于 用户6
页面77 同时被 用户2 和 用户3 推荐。
页面88 没有被推荐,因为 用户1 已经喜欢了它。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/page-recommendations
朋友关系列表:Friendship +---------------+---------+ | Column Name | Type | +---------------+---------+ | user1_id | int | | user2_id | int | +---------------+---------+ 这张表的主键是 (user1_id, user2_id)。 这张表的每一行代表着 user1_id 和 user2_id 之间存在着朋友关系。 喜欢列表:Likes +-------------+---------+ | Column Name | Type | +-------------+---------+ | user_id | int | | page_id | int | +-------------+---------+ 这张表的主键是 (user_id, page_id)。 这张表的每一行代表着 user_id 喜欢 page_id。 写一段 SQL 向user_id = 1 的用户,推荐其朋友们喜欢的页面。不要推荐该用户已经喜欢的页面。 你返回的结果中不应当包含重复项。 返回结果的格式如下例所示。 示例 1: 输入: Friendship table: +----------+----------+ | user1_id | user2_id | +----------+----------+ | 1 | 2 | | 1 | 3 | | 1 | 4 | | 2 | 3 | | 2 | 4 | | 2 | 5 | | 6 | 1 | +----------+----------+ Likes table: +---------+---------+ | user_id | page_id | +---------+---------+ | 1 | 88 | | 2 | 23 | | 3 | 24 | | 4 | 56 | | 5 | 11 | | 6 | 33 | | 2 | 77 | | 3 | 77 | | 6 | 88 | +---------+---------+ 输出: +------------------+ | recommended_page | +------------------+ | 23 | | 24 | | 56 | | 33 | | 77 | +------------------+ 解释: 用户1 同 用户2, 3, 4, 6 是朋友关系。 推荐页面为:页面23 来自于 用户2, 页面24 来自于 用户3, 页面56 来自于 用户3 以及 页面33 来自于 用户6。 页面77 同时被 用户2 和 用户3 推荐。 页面88 没有被推荐,因为 用户1 已经喜欢了它。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/page-recommendations
朋友关系列表:Friendship
+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user1_id      | int     |
| user2_id      | int     |
+---------------+---------+
这张表的主键是 (user1_id, user2_id)。
这张表的每一行代表着 user1_id 和 user2_id 之间存在着朋友关系。

喜欢列表:Likes
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| user_id     | int     |
| page_id     | int     |
+-------------+---------+
这张表的主键是 (user_id, page_id)。
这张表的每一行代表着 user_id 喜欢 page_id。

写一段 SQL 向user_id = 1 的用户,推荐其朋友们喜欢的页面。不要推荐该用户已经喜欢的页面。
你返回的结果中不应当包含重复项。

返回结果的格式如下例所示。
示例 1:
输入:
Friendship table:
+----------+----------+
| user1_id | user2_id |
+----------+----------+
| 1        | 2        |
| 1        | 3        |
| 1        | 4        |
| 2        | 3        |
| 2        | 4        |
| 2        | 5        |
| 6        | 1        |
+----------+----------+
Likes table:
+---------+---------+
| user_id | page_id |
+---------+---------+
| 1       | 88      |
| 2       | 23      |
| 3       | 24      |
| 4       | 56      |
| 5       | 11      |
| 6       | 33      |
| 2       | 77      |
| 3       | 77      |
| 6       | 88      |
+---------+---------+
输出:
+------------------+
| recommended_page |
+------------------+
| 23               |
| 24               |
| 56               |
| 33               |
| 77               |
+------------------+
解释:
用户1 同 用户2, 3, 4, 6 是朋友关系。
推荐页面为:页面23 来自于 用户2, 页面24 来自于 用户3, 页面56 来自于 用户3 以及 页面33 来自于 用户6。
页面77 同时被 用户2 和 用户3 推荐。
页面88 没有被推荐,因为 用户1 已经喜欢了它。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/page-recommendations
//测试数据
Create table If Not Exists Friendship (user1_id int, user2_id int);
Create table If Not Exists Likes (user_id int, page_id int);
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 ('1', '4');
insert into Friendship (user1_id, user2_id) values ('2', '3');
insert into Friendship (user1_id, user2_id) values ('2', '4');
insert into Friendship (user1_id, user2_id) values ('2', '5');
insert into Friendship (user1_id, user2_id) values ('6', '1');
insert into Likes (user_id, page_id) values ('1', '88');
insert into Likes (user_id, page_id) values ('2', '23');
insert into Likes (user_id, page_id) values ('3', '24');
insert into Likes (user_id, page_id) values ('4', '56');
insert into Likes (user_id, page_id) values ('5', '11');
insert into Likes (user_id, page_id) values ('6', '33');
insert into Likes (user_id, page_id) values ('2', '77');
insert into Likes (user_id, page_id) values ('3', '77');
insert into Likes (user_id, page_id) values ('6', '88');
//测试数据 Create table If Not Exists Friendship (user1_id int, user2_id int); Create table If Not Exists Likes (user_id int, page_id int); 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 ('1', '4'); insert into Friendship (user1_id, user2_id) values ('2', '3'); insert into Friendship (user1_id, user2_id) values ('2', '4'); insert into Friendship (user1_id, user2_id) values ('2', '5'); insert into Friendship (user1_id, user2_id) values ('6', '1'); insert into Likes (user_id, page_id) values ('1', '88'); insert into Likes (user_id, page_id) values ('2', '23'); insert into Likes (user_id, page_id) values ('3', '24'); insert into Likes (user_id, page_id) values ('4', '56'); insert into Likes (user_id, page_id) values ('5', '11'); insert into Likes (user_id, page_id) values ('6', '33'); insert into Likes (user_id, page_id) values ('2', '77'); insert into Likes (user_id, page_id) values ('3', '77'); insert into Likes (user_id, page_id) values ('6', '88');
//测试数据
Create table If Not Exists Friendship (user1_id int, user2_id int);
Create table If Not Exists Likes (user_id int, page_id int);

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 ('1', '4');
insert into Friendship (user1_id, user2_id) values ('2', '3');
insert into Friendship (user1_id, user2_id) values ('2', '4');
insert into Friendship (user1_id, user2_id) values ('2', '5');
insert into Friendship (user1_id, user2_id) values ('6', '1');

insert into Likes (user_id, page_id) values ('1', '88');
insert into Likes (user_id, page_id) values ('2', '23');
insert into Likes (user_id, page_id) values ('3', '24');
insert into Likes (user_id, page_id) values ('4', '56');
insert into Likes (user_id, page_id) values ('5', '11');
insert into Likes (user_id, page_id) values ('6', '33');
insert into Likes (user_id, page_id) values ('2', '77');
insert into Likes (user_id, page_id) values ('3', '77');
insert into Likes (user_id, page_id) values ('6', '88');

解题思路

根据题目要求,返回满足下列两个条件的页面:
(1)、user_id=1的用户的朋友喜欢的页面;
(2)、user_id=1的用户未标记为喜欢的页面;
对于第一个条件,我们需要先计算出user_id=1的用户的朋友是哪些。
Friendship表保存了朋友关系,因此可以从该表获取数据。不过,A与B是朋友关系,B与A同样也是朋友关系。也就是说,朋友关系是相互的。所以,可以通过如下SQL获取user_id=1的用户的朋友:

select
distinct
case when user1_id = 1 then user2_id else user1_id end user_id
from Friendship
where user1_id = 1
or user2_id = 1;
select distinct case when user1_id = 1 then user2_id else user1_id end user_id from Friendship where user1_id = 1 or user2_id = 1;
select
    distinct
    case when user1_id = 1 then user2_id else user1_id end user_id
from Friendship
where user1_id = 1
or user2_id = 1;

对于第二个条件,相当于从第一个条件过滤出的页面中,剔除已经被user_id=1的用户标记为喜欢的页面。使用NOT IN或NOT EXISTS都可以很容易的实现。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with
tmp as (
select
distinct
case when user1_id = 1 then user2_id else user1_id end user_id
from Friendship
where user1_id = 1
or user2_id = 1
)
select
distinct
a.page_id recommended_page
from Likes a
inner join tmp b
on a.user_id = b.user_id
where not exists (
select 1 from Likes c
where c.user_id = 1
and a.page_id = c.page_id);
with tmp as ( select distinct case when user1_id = 1 then user2_id else user1_id end user_id from Friendship where user1_id = 1 or user2_id = 1 ) select distinct a.page_id recommended_page from Likes a inner join tmp b on a.user_id = b.user_id where not exists ( select 1 from Likes c where c.user_id = 1 and a.page_id = c.page_id);
with
tmp as (
    select
        distinct
        case when user1_id = 1 then user2_id else user1_id end user_id
    from Friendship
    where user1_id = 1
    or user2_id = 1
)
select
    distinct
    a.page_id recommended_page
from Likes a
inner join tmp b
on a.user_id = b.user_id
where not exists (
    select 1 from Likes c
    where c.user_id = 1
    and a.page_id = c.page_id);

picture loss