订阅更新

电影评分:两个独立查询拼成一列

SQL 实战 123 题 · 第 96 题 中等 约 2 分钟读完

LeetCode 1341 · UNION ALL、各自排序取第一、并列按字典序

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

两个独立的 Top 1 查询,各自带 ORDER BY 和 LIMIT 1 并加括号,再用 UNION ALL 拼成两行。这里一定是 UNION ALL:用户名和电影名相同的话,UNION 会把两行去重成一行,结果就少了一行。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

电影表、用户表、评分表(用户给电影的评分和日期)。返回两行结果:第一行是评论电影最多的用户名(并列取字典序最小);第二行是 2020 年 2 月平均评分最高的电影名(并列取字典序最小)。

表结构

  • Movies:movie_id(主键)、title
  • Users:user_id(主键)、name
  • Movie_Rating:movie_id、user_id、rating、created_at;(movie_id, user_id) 为主键

思路

两个问题互不相关,各写一个查询:用户按评论数降序、名字升序取第一;电影限定 2 月后按平均分降序、片名升序取第一。然后把两个结果上下拼接。每个子查询要各自加括号,ORDER BY 和 LIMIT 才只作用于自己。

参考解法

select name results 
from
(
    select m.user_id ,u.name 
    from Movie_Rating m left join Users u 
    on m.user_id = u.user_id
    group by user_id
    order by count(*) desc,name
    limit 1
)t1
union 
(
select title results
from Movie_Rating r left join Movies m
on r.movie_id =m.movie_id 
where date_format(created_at,'%Y-%m')='2020-02'
group by r.movie_id
order by avg(rating) desc,title 
limit 1
)

易错点

  • 用 UNION 拼接时,如果用户名恰好和电影名相同,两行会被去重合并成一行;必须用 UNION ALL。
  • 子查询不加括号,ORDER BY ... LIMIT 会作用到整个 UNION 结果上。
刷题进度保存在当前浏览器