Внутреннее соединение и производная таблица - PullRequest
0 голосов
/ 22 июня 2019

Я пытался решить вопрос Q9 из Упражнений по запросу рейтинга фильмов SQL ( Найти разницу между средним рейтингом фильмов, выпущенных до 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

Все работает нормально, поэтому следующий шаг - присоединиться к подзапросу, который делает то же самое, но после 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 голосов
/ 22 июня 2019

Вы можете использовать условное агрегирование, чтобы получить среднее значение оценок для фильмов до и после 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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...