【问题标题】:Creating a scoring algorithm across multiple tables using MySQL使用 MySQL 创建跨多个表的评分算法
【发布时间】:2015-11-20 14:22:35
【问题描述】:

我有 3 张桌子:

(1) 部电影

id  title
1   AAA
2   BBB
3   CCC
4   DDD
5   EEE

(2) 类型

id  film_id genre
1   1       Action
2   1       Comedy
3   1       Horror
4   2       Action
5   2       Comedy
6   3       Action
7   3       Drama
8   4       Sci-Fi
9   4       Drama
10  4       Western
10  5       Romance
10  5       Musical
10  5       Avant-Garde

(3) 位董事

id  film_id director
1   1       John Smith
2   2       John Smith
3   2       Ann Coates
4   3       Tom Jones
5   4       Ann Coates
6   5       John Smith

我正在编写一个算法,它会根据与电影 #1 最接近的匹配给我一个分数 - 任何匹配的类型得分 5 分,任何匹配的导演得分 100 分。

当我只比较两个表(电影和流派)时,使用此查询的结果与预期一致:

SELECT f1.id as original_film_id, f2.id as matching_film_id, SUM(if(g1.genre = g2.genre,5,0)) as score 
FROM films f1
JOIN films f2
LEFT JOIN genres g1 ON f1.id = g1.film_id
LEFT JOIN genres g2 ON f2.id = g2.film_id
WHERE f1.id = 1 
GROUP BY f2.id
HAVING score > 0
ORDER BY score DESC;

结果:

original_film+id    matching_film_id    score
1                   1                   15
1                   2                   10
1                   3                   5

也就是说,电影#1 中的 3 个类型与电影#1 中的 3 个类型(显然)匹配,电影 #2 中的 2 个类型和电影 #3 中的 1 个类型。

但是,当我使用此查询添加到 director 表时,我不明白结果:

SELECT f1.id as original_film_id, f2.id as matching_film_id, 
SUM(if(g1.genre = g2.genre,5,0)) 
+ SUM(IF(d1.director = d2.director,100,0)) as score
FROM films f1
JOIN films f2
LEFT JOIN genres g1 ON f1.id = g1.film_id
LEFT JOIN genres g2 ON f2.id = g2.film_id
LEFT JOIN directors d1 ON f1.id = d1.film_id
LEFT JOIN directors d2 ON f2.id = d2.film_id
WHERE f1.id = 1 
GROUP BY f2.id
HAVING score > 0
ORDER BY score DESC;

我期待看到这些结果:

original_film_id    matching_film_id    score
1                   1                   115
1                   2                   110
1                   5                   100
1                   3                   5

...因为电影 #1 有相同的流派和导演,电影 #2 有 2 个相同的流派和相同的导演,电影 #5 有相同的导演但没有匹配的流派,等等。

但是我看到了这些结果:

original_film_id    matching_film_id    score
1                   1                   915
1                   2                   620
1                   5                   300
1                   3                   5

我根本不知道为什么!非常感谢所有的帮助。

【问题讨论】:

    标签: mysql mysql-workbench


    【解决方案1】:

    由于您匹配了许多行(流派行到导演行),因此您计算的分数过多。您将能够看到这一点,如果您删除 group by 和 sum,则 sum 的所有输入都将被枚举。

    您可以独立计算流派、导演的分数,然后将它们组合起来。

    select id, film_id, sum(s) as score from (
      select      a.id, c.film_id, sum(5) s
      from        films a
      left join   genres b on(a.id = b.film_id)
      left join   genres c on(b.genre = c.genre)
      where a.id = 1
      group by a.id, c.film_id
      union all
      select      a.id, c.film_id, sum(100) s
      from        films a
      left join   directors b on(a.id = b.film_id)
      left join   directors c on(b.director = c.director)
      where a.id = 1
      group by a.id, c.film_id
    ) q
    group by id, film_id
    order by id, score desc
    ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多