SQL - 按类型获取评分最高的电影
Posted
技术标签:
【中文标题】SQL - 按类型获取评分最高的电影【英文标题】:SQL - Get highest rated movie by genre 【发布时间】:2013-01-12 11:12:58 【问题描述】:我有三张桌子:
CREATE TABLE Movie
(
movieId INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR(255) NOT NULL,
moviePath VARCHAR(500) NOT NULL
);
CREATE TABLE Rating
(
rid INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
mid INTEGER FOREIGN KEY REFERENCES Movie(movieId) ON DELETE CASCADE,
uid INTEGER FOREIGN KEY REFERENCES User(id) ON DELETE CASCADE,
rating INTEGER NOT NULL,
);
CREATE TABLE Genre(
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
movieId INTEGER NOT NULL FOREIGN KEY REFERENCES Movie(movieId) ON DELETE CASCADE,
genre VARCHAR(255) NOT NULL
);
我想创建一个 sql 查询,从最常见的类型返回最常见的电影(带有电影路径、标题)。
有什么想法吗?
更新
结果:
| MID | TITLE | MOVIEPATH |
--------------------------------
| 4 | Happy days | a |
| 4 | Happy days | a |
【问题讨论】:
我认为movieId
不应该在Genre
表中,但GenreId
应该在Movie
表中。对于这样的查询,您的表不完整,您需要一些额外的详细信息。
在你当前的表格中,每个流派都可以有一部电影,但是对于我告诉过的表格,每部电影都有一个流派。
@MahdiTahsildari 真的是一部电影可以有不止一种类型吗?在将示例数据添加到 OP 表时,我考虑到了这一点,因为它是没有示例数据的盲目猜测..
【参考方案1】:
如果您提供了一些匹配的示例数据,那就太好了。试试这个吧。看看你之前的问题,这个答案是草拟的。
SQLFIDDLE DEMO
select t.mid, t.sum_rating,
m.title, m.moviepath, g.genres
from (
select mid,
sum(rating) as sum_rating,
dense_rank() over (order by
sum(rating) desc) as rnk
from rating
group by mid
) t
left join movie m
on m.movieid = t.mid
left join genre g
on g.movieid = m.movieid
where t.rnk = 1;
结果:
| MID | SUM_RATING | TITLE | MOVIEPATH | GENRES |
------------------------------------------------------
| 4 | 37 | Happy days | a | comedy |
| 4 | 37 | Happy days | a | RomCom |
您可以使用此替代方案,因为 HSQL 不支持 dense_rank
:
查询:order by desc and top 1
-- alternatively
select t.mid, t.sum_rating,
m.title, m.moviepath, g.genres
from (
select top 1 mid,
sum(rating) as sum_rating
from rating
group by mid
order by sum_rating desc
) t
left join movie m
on m.movieid = t.mid
left join genre g
on g.movieid = m.movieid
;
【讨论】:
hsql 不支持dense_rank()。没有dense_rank有没有可能的解决方案? @maximus 这是你需要的)我的意思是预期的结果)?请澄清,注意我使用的示例数据,如果您需要对示例数据和表结构进行任何更改,请发表评论。如果是这样,我们可以使用 HSQL 的其他方法获得相同的结果.. 我只需要中间,标题,电影路径 @maximus 我已经更新了替代方法。请看一下。另外,请确认一部电影是否可以在您的设计中包含多个流派以确保我们自己的理智:) 所以我们知道我们遵循的表模式是正确的。 @maximus 您可以简单地从select clause
中删除genres
列,以确保您获得预期的结果并将distinct
添加到select claues
,因为您不想返回同一数据行两次..【参考方案2】:
您可以通过在子查询中对电影的所有评分求和来计算评分。另一个子查询可以计算每种类型的最高评分。通过将它们连接在一起,您将只过滤每种类型的热门电影:
select *
from Movie m
join Genre g
on g.movieId = m.movieId
join (
select r.mid
, sum(Rating) as SumRating
from Rating r
group by
r.mid
) r
on r.mid = m.movieId
join (
select g.id as gid
, max(SumRating) as MaxGenreRating
from (
select r.mid
, sum(Rating) as SumRating
from Rating r
group by
r.mid
) r
join Genre g
on g.movieId = r.mid
group by
g.id
) filter
on filter.gid = g.id
and filter.MaxGenreRating = r.SumRating
【讨论】:
【参考方案3】:我们在哪里可以找到观看次数?使用此表,您可以使用如下查询找到评分最高的电影:
select Movie.movieId, Movie.title, Movie.moviepath
from movie, rating, genre
where
movie.id = rating.mid and
movie.id = genre.movieId
order by rating desc
limit 1; // limit is used if you are using mysql. In other databases you can use suitable sql query.
但是,如果您要从最常见的类型中寻找最常见的电影,则您必须在表格中了解每部电影和每种类型的观看次数。
【讨论】:
【参考方案4】:我可以建议您在评分上使用聚合最大值以及根据流派分组
select max(Rating.rating) as max_rating, Genre.genre, Movie.movieId from Movie
inner join Rating on Movie.movieId = Rating.mid
inner join Genre on Movie.movieId = Genre.movieId
group by Genre.genre;
我不太确定这是否会 100% 有效,因为我没有尝试过,但我的想法是使用 group by。它可以与 count、max、min、avg 等聚合一起使用。
希望对你有帮助
【讨论】:
以上是关于SQL - 按类型获取评分最高的电影的主要内容,如果未能解决你的问题,请参考以下文章