2015-06-10 34 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。