文章目录
- 题目需求
- 思路一:使用 Except
- 实现一
- 实现二:使用 Except
- 思路三:使用 full outer join + where
- 实现三
- 实现四:使用 not in + concat
- 题目来源
题目需求
现请向所有用户推荐其朋友收藏但是用户自己未收藏的商品,请从好友关系表(friendship_info)和收藏表(favor_info)中查询出应向哪位用户推荐哪些商品。
期望结果如下:
user_id (用户id) | sku_id (应向该用户推荐的商品id) |
---|---|
101 | 2 |
101 | 4 |
101 | 7 |
… | … |
需要用到的表:
好友关系表:friendship_info
user1_id(用户1 id) | user2_id(用户2 id) |
---|---|
101 | 1010 |
101 | 108 |
101 | 106 |
收藏表:favor_info
user_id(用户id) | sku_id(商品id) | create_date(收藏日期) |
---|---|---|
101 | 3 | 2021-09-23 |
101 | 12 | 2021-09-23 |
101 | 6 | 2021-09-25 |
思路一:使用 Except
实现一
-- 方法一: 感谢网友 (A except B : 返回仅出现在A中的记录。注: except 时两个表的 字段名、字段顺序 要一致)
-- Except学习链接: http://t.csdn.cn/L2LuH
-- 1)用户user1_id 的朋友收藏的商品sku_id
select friendship_info.user1_id as user_id, sku_id
from friendship_info
join favor_info
on friendship_info.user2_id = favor_info.user_id
except --取补集(差集)
-- 2)自己收藏的商品
select user_id, sku_id
from favor_info;
实现二:使用 Except
-- 方法二: 我的方法, 也是使用的 Except(与 思路一 大致相同)
select distinct user_id,
sku_id
from (
-- 1)查询出所有 ‘朋友’ 收藏的 sku_id
select user1_id user_id,
user2_id,
sku_id
from friendship_info
join favor_info on friendship_info.user2_id = favor_info.user_id
except
-- 2)查询出所有 ‘我’ 收藏的 sku_id
select user1_id user_id,
user2_id,
sku_id
from friendship_info
join favor_info on friendship_info.user1_id = favor_info.user_id
) t1;
思路三:使用 full outer join + where
实现三
-- 方法三: 我的方法, 不使用 Except
-- 在Hive中,没有直接的 EXCEPT 操作符。但是可以通过其他方式实现类似的功能。例如,可以使用 JOIN 和 WHERE 子句来实现两个表的差集操作。
-- 注: Hive 确实不支持expect函数,但是hive支持expect子句进行语法运算。
select distinct t1.user1_id as user_id,
t1.sku_id sku_id
from (
-- 1)查询出所有 ‘朋友’ 收藏的 sku_id
select user1_id,
user2_id,
sku_id
from friendship_info
left join favor_info on friendship_info.user2_id = favor_info.user_id
) t1
full outer join
(
-- 2)查询出所有 ‘我’ 收藏的 sku_id
select user1_id,
user2_id,
sku_id
from friendship_info
left join favor_info on friendship_info.user1_id = favor_info.user_id
) t2
on t1.user1_id = t2.user1_id and t1.user2_id = t2.user2_id and t1.sku_id = t2.sku_id
where t2.user1_id is null;
实现四:使用 not in + concat
-- 方法四: 与 思路一 相似
-- 3) 查询出所有 ‘朋友’ 收藏了 但是 ‘我’ 没有收藏的 sku_id
SELECT t1.user1_id user_id, t2.sku_id
-- 1) 查询出所有 ‘朋友’ 收藏的 sku_id
from friendship_info t1
JOIN favor_info t2
on t1.user2_id = t2.user_id
where concat(t1.user1_id, t2.sku_id) not in (
-- 2)查询出所有 ‘我’ 收藏的 sku_id
SELECT concat(user_id, sku_id)
from favor_info
)
-- group by 在此处相当于对 t1.user1_id, t2.sku_id 进行去重
group by t1.user1_id, t2.sku_id;
-- 等价于 使用 distinct
SELECT distinct t1.user1_id user_id, t2.sku_id
from friendship_info t1
JOIN favor_info t2
on t1.user2_id = t2.user_id
where concat(t1.user1_id, t2.sku_id) not in (
SELECT concat(user_id, sku_id)
from favor_info
);
题目来源
http://practice.atguigu.cn/#/question/14/desc?qType=SQL