电影评分:两个独立查询拼成一列
LeetCode 1341 · UNION ALL、各自排序取第一、并列按字典序
面试怎么回答
两个独立的 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 结果上。