HiveSQL 面试题 - 向用户推荐朋友收藏的商品

1 需求

现需要请向所有用户推荐其朋友收藏但是用户自己未收藏的商品,请从好友关系表(friendship_info)和收藏表(favor_info)中查询出应向哪位用户推荐哪些商品。

  • 好友关系表 friendship_info
user1_id(用户1 id)user2_id(用户2 id)
1011010
101108
101106
  • 收藏表 favor_info
user_id(用户id)sku_id(商品id)create_date(收藏日期)
10132021-09-23
101122021-09-23
10162021-09-25
  • 期望结果
user_id (用户id)sku_id (应向该用户推荐的商品id)
1012
1014
1017
1019
1018
10111
1011

2 实现

  • 思路

初看这个需求还是有些绕的,而且实现过程中需要注意很多细节否则就会导致出错。

主思路是统计出每个用户自己收藏的商品和自己的朋友收藏的商品,然后从中取出朋友收藏的且自己未收藏的商品,用来给自己推荐。需要注意好友关系表中的关系是双向的,与收藏表进行关联时,关联字段的不同拿出来的数据也是不同的。

  • 实现

1 查出每个人的朋友都收藏了哪些商品,注意关联字段 user2_id,表示查询朋友收藏的商品

SELECT *
from friendship_info
     inner join
     favor_info
     on friendship_info.user2_id = favor_info.user_id

查询部分数据如下,其中 sku_id 字段为朋友 user2_id 收藏的商品

user1_iduser2_iduser_idsku_idcreate_date
10110210212021-09-24
10110210222021-09-24
10110210282021-09-23
101102102122021-09-22
101102102112021-09-23
10110210292021-09-25
10110210242021-09-25
10110210262021-09-23
10110210272021-09-26
10110410492021-09-28
10110410472021-09-28
10110410482021-09-25
10110410432021-09-28
101104104112021-09-25
10110410462021-09-25
101104104122021-09-28
101106106122021-10-08
10110610612021-10-08
10110610642021-10-04
10110610652021-10-08
10110610622021-10-04
10110610662021-10-04
10110610672021-10-08
10110810892021-10-08
10110810832021-10-10
10110810882021-10-10
101108108102021-10-07
101108108112021-10-07
1011010101022021-09-29
1011010101092021-09-29
1011010101012021-10-01

2 对结果 1 进行简化,因为某个用户的多个朋友可能会收藏相同的商品,以下 SQL 查出来某个用户的所有的朋友的收藏信息

SELECT user1_id,
       sku_id sku_id_friend
from friendship_info
     inner join favor_info on friendship_info.user2_id = favor_info.user_id
group by user1_id, sku_id
user1_idsku_id_friend
1011
10110
10111
10112
1012
1013
1014
1015
1016
1017
1018
1019

3 找出每个人自己都收藏了哪些商品,为了方便比较,这里将每个人自己的收藏使用 collect_list(sku_id) 收集到集合中

select user_id, collect_list(sku_id) sku_id_self
from favor_info
group by user_id
user_idsku_id_self
101[“3”,“12”,“6”,“10”,“5”]
1010[“2”,“9”,“1”]
102[“1”,“2”,“8”,“12”,“11”,“9”,“4”,“6”,“7”]
103[“8”,“5”,“6”,“12”,“7”,“10”,“4”,“11”,“3”]
104[“9”,“7”,“8”,“3”,“11”,“6”,“12”]
105[“8”,“9”,“7”,“11”,“5”,“4”,“10”]
106[“12”,“1”,“4”,“5”,“2”,“6”,“7”]

4 关联两份数据,使用 !array_contains(sku_id_self, sku_id_friend) 从中筛选出最终结果

select user_id, sku_id_friend sku_id
from (SELECT user1_id, sku_id sku_id_friend
      from friendship_info
           inner join favor_info on friendship_info.user2_id = favor_info.user_id
      group by user1_id, sku_id) t1
     right join (select user_id, collect_list(sku_id) sku_id_self from favor_info group by user_id) t2
                on t1.user1_id = t2.user_id
where !array_contains(sku_id_self, sku_id_friend)
user_idsku_id
1011
1019
1018
1017
1014
1012
10111
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值