Не может отфильтровать ноль, даже реализовал в где функция - PullRequest
0 голосов
/ 07 апреля 2019

Три таблицы: -Рейтинг (rID, mID, звезды, ratingDate) Фильм (mID, название, год, режиссер) Рецензент (rID, имя)

Найти разницу между средней оценкой фильмов, выпущенных до 1980 года, и средней оценкой фильмов, выпущенных после 1980 года.

(Обязательно рассчитайте среднюю оценку для каждого фильма, а затем среднюю из этих средних для фильмов до 1980 года и фильмов после. Не просто рассчитывайте общую среднюю оценку до и после 1980 года.)

Но всегда есть ноль, даже если я отфильтровал ноль, где функция

''''
select r.mID,sum(stars),
count(case when year>1980 and stars is not null then stars end )as "numaf",
count(case when year<1980 and stars is not null then stars end )as "numbf",
sum(case when year>1980 and stars is not null then stars end )as "sumaf",
sum(case when year<1980 and stars is not null then stars end )as "sumbf",
(("sumaf"/"numaf")-("sumbf"/"numbf")) as "difof"
from Rating r left join movie m on r.mID = m.mID 
where stars is not null
group by r.mID
''''

and this is output, always has "NULL":
101 9   0   3   <NULL>  9   <NULL>
103 5   0   2   <NULL>  5   <NULL>
104 5   2   0   5   <NULL>  <NULL>
106 9   0   2   <NULL>  9   <NULL>
107 8   2   0   8   <NULL>  <NULL>
108 10  3   0   10  <NULL>  <NULL>

Ответы [ 2 ]

1 голос
/ 07 апреля 2019

Средний рейтинг фильмов:

select r.mID, avg(stars) as avg_stars
from Rating r 
group by r.mID;

Затем, чтобы ответить на вопрос, вы можете присоединить его к фильмам и использовать условную агрегацию:

select avg(case when year < 1980 then avg_stars) as avg_stars_pre1980,
       avg(case when year > 1980 then avg_stars) as avg_stars_post1980,
       (avg(case when year < 1980 then avg_stars) -
        avg(case when year > 1980 then avg_stars) a
       ) as diff       
from (select r.mID, avg(stars) as avg_stars
      from Rating r 
      group by r.mID
     ) r join
     movie m
     on r.mID = m.mID 
group by r.mID;

Причина, по которой выполучение NULL происходит потому, что вы думаете , что вы разделяете псевдонимы столбцов, определенные в SELECT.Тем не менее, вы действительно разделяете строки.Итак:

(("sumaf"/"numaf")-("sumbf"/"numbf")) as "difof"

это просто:

(('sumaf'/'numaf')-('sumbf'/'numbf')) as difof

Строки интерпретируются как числа в числовой константе, причем начальные цифры преобразуются в число.У них нет начальных цифр, поэтому все значения равны 0, что приводит к делению на ноль.MySQL возвращает NULL для деления на ноль вместо генерирования ошибки.

1 голос
/ 07 апреля 2019

Чтобы получить средний рейтинг фильмов до и после 1980 года, вы можете сделать что-то вроде:

SELECT SUM(avgRating)/Count(mID), yearSection
FROM (
    SELECT 
       r.mid,
       round(sum(stars),2)/count(r.mID) as avgRating,
       case when year > 1980 then 1 else 0 end as yearSection
from Rating r left join movie m on r.mID = m.mID 
where stars is not null
group by r.mID
     )AS foo
GROUP BY yearSection

Это не приведет к нулевым значениям. Также вам нужно округлить сумму до десятичной точки, иначе ваши средние значения будут неверными.

...