内连接和派生 table
Inner join and derived table
我一直在尝试从SQL Movie-Rating Query Exercises中解决Q9(找出之前发布的电影的平均评分之间的差异1980 年和 1980 年以后发行的电影的平均评分。 )。由于几乎每部电影都有不止一个评分(星级),我需要计算每部电影的第一个平均评分。我正在通过以下代码执行此操作:
SELECT
AVG(rating.stars)
FROM Rating
INNER JOIN movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year < 1980
在下一步中,我将上面的代码放入主查询中,该查询将计算 1980 年之前和 1980 年之后的平均评分之间的差异。但首先我想看看是否一切正常。让我们找出答案:
SELECT
before.AVG_before1980
FROM
(
SELECT
AVG(rating.stars) as AVG_before1980
FROM Rating
INNER JOIN movie ON rating.mid = movie.mid
GROUP BY rating.mID
HAVING year < 1980
) AS before
输出:
AVG_before1980
3.0
2.5
4.5
一切正常,所以下一步是 JOIN 子查询,它执行相同但在 1980 年之后:
SELECT
before.AVG_before1980, after.AVG_after1980
FROM
(
SELECT
AVG(rating.stars) as AVG_before1980
FROM
Rating
INNER JOIN
movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year < 1980
) AS before
INNER JOIN
(
SELECT
AVG(rating.stars) as AVG_after1980
FROM
Rating
INNER JOIN
movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year > 1980
) AS after
不幸的是输出与我预期的不一样:
AVG_before_1980 AVG_after1980
2.5 4.0
2.5 3.33333333333333
2.5 2.5
4.0 4.0
4.0 3.33333333333333
4.0 2.5
3.33333333333333 4.0
3.33333333333333 3.33333333333333
我以为会是:
AVG_before1980 AVG_after1980
3.0 2.5
2.5 4.0
4.5 3.33333333333333
问题很简单:我必须做什么才能获得上述输出?如果有人可以向我解释我做错了什么,那就太好了。请随时改进我的代码。
所有需要的表格:https://lagunita.stanford.edu/c4x/DB/SQL/asset/moviedata.html
您可以使用条件聚合来获取 1980 年前后电影的评分 的平均值:
SELECT AVG(CASE WHEN m.year < 1980 THEN r.stars END) as avg_pre1980,
AVG(CASE WHEN m.year > 1980 THEN r.stars END) as avg_post1980
FROM Rating r INNER JOIN
movie m
ON r.mid = m.mid ;
要获得 电影 的平均值,您需要先按电影聚合,然后再聚合:
SELECT AVG(CASE WHEN m.year < 1980 THEN avg_stars END) as avg_pre1980,
AVG(CASE WHEN m.year > 1980 THEN avg_stars END) as avg_post1980
FROM (SELECT m.id, year, AVG(r.stars) as avg_stars
FROM Rating r INNER JOIN
movie m
ON r.mid = m.mid
GROUP BY m.id, m.year
) my
您没有指定您的数据库,但有些数据库使用整数算法进行除法和平均,因此您应该转换为 non-integer 数字以获得更准确的平均值:AVG(r.stars * 1.0)
.
我一直在尝试从SQL Movie-Rating Query Exercises中解决Q9(找出之前发布的电影的平均评分之间的差异1980 年和 1980 年以后发行的电影的平均评分。 )。由于几乎每部电影都有不止一个评分(星级),我需要计算每部电影的第一个平均评分。我正在通过以下代码执行此操作:
SELECT
AVG(rating.stars)
FROM Rating
INNER JOIN movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year < 1980
在下一步中,我将上面的代码放入主查询中,该查询将计算 1980 年之前和 1980 年之后的平均评分之间的差异。但首先我想看看是否一切正常。让我们找出答案:
SELECT
before.AVG_before1980
FROM
(
SELECT
AVG(rating.stars) as AVG_before1980
FROM Rating
INNER JOIN movie ON rating.mid = movie.mid
GROUP BY rating.mID
HAVING year < 1980
) AS before
输出:
AVG_before1980
3.0
2.5
4.5
一切正常,所以下一步是 JOIN 子查询,它执行相同但在 1980 年之后:
SELECT
before.AVG_before1980, after.AVG_after1980
FROM
(
SELECT
AVG(rating.stars) as AVG_before1980
FROM
Rating
INNER JOIN
movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year < 1980
) AS before
INNER JOIN
(
SELECT
AVG(rating.stars) as AVG_after1980
FROM
Rating
INNER JOIN
movie ON rating.mid = movie.mid
GROUP BY
rating.mID
HAVING
year > 1980
) AS after
不幸的是输出与我预期的不一样:
AVG_before_1980 AVG_after1980
2.5 4.0
2.5 3.33333333333333
2.5 2.5
4.0 4.0
4.0 3.33333333333333
4.0 2.5
3.33333333333333 4.0
3.33333333333333 3.33333333333333
我以为会是:
AVG_before1980 AVG_after1980
3.0 2.5
2.5 4.0
4.5 3.33333333333333
问题很简单:我必须做什么才能获得上述输出?如果有人可以向我解释我做错了什么,那就太好了。请随时改进我的代码。
所有需要的表格:https://lagunita.stanford.edu/c4x/DB/SQL/asset/moviedata.html
您可以使用条件聚合来获取 1980 年前后电影的评分 的平均值:
SELECT AVG(CASE WHEN m.year < 1980 THEN r.stars END) as avg_pre1980,
AVG(CASE WHEN m.year > 1980 THEN r.stars END) as avg_post1980
FROM Rating r INNER JOIN
movie m
ON r.mid = m.mid ;
要获得 电影 的平均值,您需要先按电影聚合,然后再聚合:
SELECT AVG(CASE WHEN m.year < 1980 THEN avg_stars END) as avg_pre1980,
AVG(CASE WHEN m.year > 1980 THEN avg_stars END) as avg_post1980
FROM (SELECT m.id, year, AVG(r.stars) as avg_stars
FROM Rating r INNER JOIN
movie m
ON r.mid = m.mid
GROUP BY m.id, m.year
) my
您没有指定您的数据库,但有些数据库使用整数算法进行除法和平均,因此您应该转换为 non-integer 数字以获得更准确的平均值:AVG(r.stars * 1.0)
.