内部联接和派生表

时间:2019-06-22 12:22:15

标签: sql inner-join derived-table

我一直在尝试通过 SQL电影评分查询练习解决第9季度问题,找出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

1 个答案:

答案 0 :(得分:0)

您可以使用条件聚合来获得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

您没有指定数据库,但是有些数据库使用整数算术除法和平均值,因此您应该转换为非整数以获得更准确的平均值:AVG(r.stars * 1.0)