2015-11-20 62 views
0

多個表的計分算法我有3個表:創建跨越使用MySQL

(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 

也就是說,在電影3個類型#1與電影#1(顯然)中的3種類型相匹配,#2與電影#2中的2種類型以及電影#3中的1種類型匹配。

不過,我不明白的結果,當我使用此查詢的董事表中添加:

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 

而我根本無法弄清楚爲什麼!感謝所有的幫助。

回答

0

由於您匹配了很多行(流派行與導演行),因此您已經在計算分數。你將能夠看到這一點,如果你刪除了組和總和,所有的總和輸入將被枚舉。

您可以獨立計算流派,導演的分數,然後將它們組合。

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 
; 
+0

這是非凡的,非常感謝你。 – huey