2015-06-10 95 views
1

有一個用戶排列電影的數據集。需要找到與user1相似口味的用戶。定義如下類似的味道:考慮user1genre的平均評級爲avgr1並從user2相同種類avgr2,然後user1user2有相似的味道是abs(avgr1-avgr2)<1。到目前爲止,我能夠獲得名稱,類型和平均值之間的絕對值,但用於比較的篩選不起作用。比較平均值 - SPARQL

SELECT ?p ?p1 ?genre (abs (AVG(?rating)-AVG(?ratingp1)) AS ?RDiff) 
WHERE{ 
?p movies:hasRated ?rate. 
?p1 foaf:knows ?p. 
?rate movies:ratedMovie ?mov. 
?rate movies:hasRating ?rating. 
?mov movies:hasGenre ?genre. 
?p1 movies:hasRated ?ratep1. 
?ratep1 movies:ratedMovie ?movp1. 
?ratep1 movies:hasRating ?ratingp1. 
?movp1 movies:hasGenre ?genre. 
FILTER (xsd:float(?Rdiff)<1.0 && ?p=movies:user1) 
} 
GROUP BY ?p ?p1 ?genre 
+1

看着你的編輯,看起來你問了一個問題,然後我的答案爲它工作(因爲你把它加入到這個最新版本)。最新版本似乎在提出一個新問題。如果您找到了原始問題的答案,那麼您將答案標記爲已接受。如果您有新問題,則應將其作爲新問題發佈,而不要編輯原始問題。通過編輯原稿,可以使發佈給它的答案失效。我回滾了這個問題(但修訂版本仍然可以在修訂歷史中找到)。 –

回答

3

如果沒有一些樣本數據可以處理這些問題很難回答這些問題。下面是一個有誰對喜劇類似的排名上浪漫的兩個用戶,但不同的排名一些樣本數據:

@prefix : <urn:ex:> 

:a :ranks [ :genre :comedy ; :value 2 ], 
      [ :genre :comedy ; :value 3 ], 
      [ :genre :comedy ; :value 3 ], 
      [ :genre :romance ; :value 7 ], 
      [ :genre :romance ; :value 8 ], 
      [ :genre :romance ; :value 9 ]. 

:b :ranks [ :genre :comedy ; :value 3 ], 
      [ :genre :comedy ; :value 3 ], 
      [ :genre :comedy ; :value 4 ], 
      [ :genre :romance ; :value 0 ], 
      [ :genre :romance ; :value 1 ], 
      [ :genre :romance ; :value 0 ]. 

下面是計算它們的平均排名在流派的不同的查詢:

prefix : <urn:ex:> 

select ?user1 ?user2 ?genre (abs(avg(?value1)-avg(?value2)) as ?diff) { 
    ?user1 :ranks [ :genre ?genre ; :value ?value1 ]. 
    ?user2 :ranks [ :genre ?genre ; :value ?value2 ]. 
    filter (str(?user1) < str(?user2)) #-- avoid duplicate user1/user2, user2/user1 results 
} 
group by ?user1 ?user2 ?genre 
order by ?diff 
--------------------------------------------------------- 
| user1 | user2 | genre | diff      | 
========================================================= 
| :a | :b | :comedy | 0.666666666666666666666667 | 
| :a | :b | :romance | 7.666666666666666666666667 | 
--------------------------------------------------------- 

現在,你不能過濾器對總結果,你必須使用,所以只有在差異小於某個特定值的值,你會這樣做:

prefix : <urn:ex:> 

select ?user1 ?user2 ?genre (abs(avg(?value1)-avg(?value2)) as ?diff) { 
    ?user1 :ranks [ :genre ?genre ; :value ?value1 ]. 
    ?user2 :ranks [ :genre ?genre ; :value ?value2 ]. 
    filter (str(?user1) < str(?user2)) 
} 
group by ?user1 ?user2 ?genre 
having (?diff < 1) 
order by ?diff 
-------------------------------------------------------- 
| user1 | user2 | genre | diff      | 
======================================================== 
| :a | :b | :comedy | 0.666666666666666666666667 | 
-------------------------------------------------------- 

如果你不關心實際的差異,不同的是它是低於閾值,就可以把在直接有的表達,並做到:

select ?user1 ?user2 ?genre { 
    #-- ... 
} 
group by ?user1 ?user2 ?genre 
having (abs(avg(?value1)-avg(?value2)) < 1) 
+0

添加了示例數據集。而編輯任務 – nlimits

+0

@nlimits但這個答案適合你嗎?在如何檢索實際排名方面存在差異,但清楚地知道如何執行該部分(因爲您有現有的查詢)。關於**組和**有**的部分應該很容易翻譯,是嗎? –

0

?在FILTER中未定義Rdiff - 發生在SELECT之前的AS之前。

嘗試使用HAVING,後面跟着GROUP BY。