Получить фильмы в порядке максимально распространенных жанров, а затем ключевые слова - PullRequest
1 голос
/ 14 апреля 2019

У меня есть следующая таблица Фильмы:

id    |                  title                           |    year 
315      Harry Potter and the Deathly Hallows: Part 2         2011
407      Cinderella                                           2015
826      The Shape of Water                                   2017
799      Enchanted                                            2007
523      How to Train Your Dragon                             2010
618      Crazy Rich Asians                                    2018

и таблица Жанры:

movie_id   |    genre
315             adventure
315             fantasy
315             mystery
315             drama
407             drama
407             fantasy
826             drama
826             thriller
826             adventure
826             horror
799             fantasy
799             comedy
799             romance
523             drama
523             fantasy
618             romance
618             comedy

и ключевое слово таблицы:

movie_id     |       keyword 
315                  magic
315                  wizards
315                  witch
315                  friendship
315                  abuse 
407                  prince 
407                  fairy tale
407                  magic
407                  poor girl
407                  abuse 
826                  scientist
826                  mute
826                  friendship
799                  musical
799                  magic
799                  witch
799                  friendship
523                  viking
523                  boy
523                  fire
618                  singapore
618                  wedding
618                  money

Я пытаюсьпостроить запрос, который выводит все фильмы, которые имеют общие жанры для данного фильма.Если есть фильмы, которые имеют одинаковое количество общих жанров, то я хочу ранжировать эти фильмы по порядку максимальных общих ключевых слов.

Например, если фильм был «Гарри Поттер и Дары смерти: Часть 2», тогда результат запроса будет:

title                      |      genre_frequency     |    keyword_frequency
Cinderella                        2                        2
The Shape of Water                2                        1
How to Train Your Dragon          2                        0
Enchanted                         1                        3

Фильмы, у которых нет жанров, общих для указанного фильма, не включаются в вывод (например, Crazy Rich Asians).

У меня есть два запроса, которые могут дать мне genre_frequency и keyword_frequency.

select m.*, genre_frequency from movie m
join (
     select m.id, count(*) as genre_frequency
     from movie m
     join genre g on m.id=g.movie_id
     where g.genre in (select g1.genre 
                       from genre g1
                       where g1.movie_id=315)
     group by m.id
     ) f
 on m.id=f.id
 where m <> 315
 order by f.genre_frequency desc;


select m.*, keyword_frequency from movie m
join (
     select m.id, count(*) as keyword_frequency
     from movie m
     join keyword k on m.id=k.movie_id
     where k.keyword in (select k1.keyword
                       from keyword k1
                       where k1.movie_id=315)
     group by m.id
     ) f
 on m.id=f.id
 where m <> 315
 order by f.keyword_frequency desc;

Проблема в том, что я хочу объединить два вышеупомянутых запроса в один запрос, чтобы я мог получить выходную таблицу, как показано выше.Я не уверен, как я могу это сделать.Любые идеи приветствуются.

Ответы [ 2 ]

2 голосов
/ 14 апреля 2019

Можно попробовать использовать UNION ALL, объединить таблицы Genres и keyword и добавить столбец grp, чтобы разделить две части для набора результатов.затем используйте агрегирующую функцию условия.

Запрос # 1

select m.title, 
      count(CASE WHEN t1.grp = 'g' THEN 1 END) as genre_frequency,
      count(CASE WHEN t1.grp = 'k' THEN 1 END) as keyword_frequency
from Movies m
join (
    SELECT movie_id,genre name,'g' grp
    FROM Genres 
    UNION ALL
    SELECT movie_id,keyword,'k' grp
    FROM keyword
) t1 on m.id=t1.movie_id
where (t1.name in (select g1.genre 
               from Genres g1
               where g1.movie_id=315) or 
      t1.name in (select k1.keyword 
               from keyword k1
               where k1.movie_id=315)) 
AND m.id <> 315
group by m.title;

| title                    | genre_frequency | keyword_frequency |
| ------------------------ | --------------- | ----------------- |
| Cinderella               | 2               | 2                 |
| Enchanted                | 1               | 3                 |
| How to Train Your Dragon | 2               | 0                 |
| The Shape of Water       | 2               | 1                 |

Просмотр на БД Fiddle

0 голосов
/ 14 апреля 2019

запрос, приведенный ниже, сначала включает все фильмы и объединяет их с фильмами, которые имеют общие жанры с фильмом, который вы ищете.это позволит избавиться от любых фильмов без жанров, общих с фильмом, по которому нужно искать.

Я использую ваш запрос частоты жанра в качестве производной таблицы в этом случае.Я также удалил предложение IN в операторе where и использовал другое внутреннее соединение для повышения производительности.

вторая производная таблица, объединенная с помощью LEFT JOIN - это запрос, который вы использовали для получения частоты ключевых слов.та же логика применима к таблице частот жанров, единственное отличие - это ЛЕВОЕ СОЕДИНЕНИЕ, поскольку два фильма могут иметь общие жанры, но не ключевые слова.

обратите внимание на оператор IFNULL в предложении select, чтобы мы возвращали 0, если не найдено ключевых слов, которые являются общими.

В конце мы просто сортируем сначала по частоте жанра, а затем по частоте ключевых слов в порядке убывания.

select m.title, IFNULL(g_fq.genre_frequency,0), 
IFNULL(k_fq.keyword_frequency,0)
FROM movie m
INNER JOIN 
(select m.id as movie_id, genre_frequency from movie m
join (
     select m.id, count(*) as genre_frequency
     from movie m
     join genre g on m.id=g.movie_id
     INNER JOIN 
       (select g1.genre 
       from genre g1
       where g1.movie_id=315) as a on a.genre=g.genre
     group by m.id
     ) f
 on m.id=f.id
 where m.id <> 315
 ) as g_fq ON m.id=g_fq.movie_id

 LEFT JOIN 
 (
select m.id as movie_id, keyword_frequency from movie m
join (
     select m.id, count(*) as keyword_frequency
     from movie m
     join keyword k on m.id=k.movie_id
     INNER JOIN
      (select k1.keyword
       from keyword k1
       where k1.movie_id=315) as b on b.keyword=k.keyword
     group by m.id
     ) f
 on m.id=f.id
 where m.id <> 315
 ) as k_fq on m.id=k_fq.movie_id
 order by IFNULL(g_fq.genre_frequency,0) DESC,IFNULL(k_fq.keyword_frequency,0) DESC


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