内连接和派生 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).