SPARQL对聚合值

时间:2016-02-22 12:27:46

标签: sparql rdf semantic-web ontology

我有这个问题:

prefix : <http://test.example/> 

select  ?anotherUser  (COUNT(?anotherItem) as ?countOfSharedLikedItems) 
WHERE 
{
   values ?user {:ania}.
   ?anotherUser :likes ?anotherItem.

   filter (?anotherUser != ?user)
   filter exists {?user :likes ?anotherItem}
}
group by ?anotherUser
order by desc(?countOfSharedLikedItems)

该数据运行:

@prefix : <http://test.example/> .

:alice :likes :beethoven.
:alice :likes :verdi.
:sofia :likes :beethoven.
:sofia :likes :verdi.
:sofia :likes :rossini.
:sofia :likes :mozart.
:ania :likes :verdi.
:ania :likes :beethoven.
:ania :likes :david.
:david :likes :ania.
:david :likes :beethoven.
:david :likes :verdi.
:antonino :likes :verdi.
:antonino :likes :mozart.
:weirdo :likes :katyperry.
:beethoven a :recommendable.
:verdi a :recommendable.
:rossini a :recommendable.
:katyperry a :recommendable.
:mozart a :recommendable.

它工作正常,我正在进行聚合并将值绑定到名为countOfSharedLikedItems的变量。现在我想获得该参数的最大值,我试过这个:

prefix : <http://test.example/> 

select  
   ?anotherUser 
   (MAX(?countOfSharedLikedItems) as ?max) 
   (COUNT(?anotherItem) as ?countOfSharedLikedItems)  
WHERE 
{
   values ?user { :ania }.
   ?anotherUser :likes ?anotherItem.

   filter (?anotherUser != ?user)
   filter exists { ?user :likes ?anotherItem }
}
group by ?anotherUser
order by desc(?countOfSharedLikedItems)

但变量max的结果始终为空。

我做错了什么?

提示我确实需要输出中的三个变量anotherUsercountOfSharedLikedItemsmax。否则,我会做一个外部选择,我可以获得最大值,但我需要其中的三个,这就是我要问的原因,因为我自己无法做到这一点

更新1

我尝试了这个 SILLY 解决方案,它有效,但显然很傻

prefix : <http://test.example/> 
select ?anotherUser ?countOfSharedLikedItems ?maxSharedLikedItems 
WHERE {
{
   select  
      ?anotherUser  
      (COUNT(?anotherItem) as ?countOfSharedLikedItems)  
   WHERE 
   {     
      values ?user { :ania }.
      ?anotherUser :likes ?anotherItem.

      filter (?anotherUser != ?user)
      filter exists { ?user :likes ?anotherItem }
   }
   group by ?anotherUser
   order by desc(?countOfSharedLikedItems)
}
{
   select (MAX(?countOfSharedLikedItems) as ?maxSharedLikedItems) 
   WHERE 
   {
       select  
          ?anotherUser  
          (COUNT(?anotherItem) as ?countOfSharedLikedItems)  
       WHERE 
       {
          values ?user { :ania }.
          ?anotherUser :likes ?anotherItem.

          filter (?anotherUser != ?user)
          filter exists { ?user :likes ?anotherItem }
       }
       group by ?anotherUser
   }
}
}

你能检查一下并提出另一个更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

最外层查询的结构在这些部分中存在致命问题:

select  
   (MAX(?countOfSharedLikedItems) as ?max) 
   (COUNT(?anotherItem) as ?countOfSharedLikedItems)  
WHERE { ... }
group by ?anotherUser

您需要完全了解分组的内容。 其中部分中的三元组提供了一堆结果行。例如,在像

这样的查询中
select * where {
  ?s ?p ?o 
}

结果是一堆行,每行都有一个每个变量的值。当您添加 group by 子句时,您说要将这些行分区为一堆集。例如,如果结果是

s1 p1 o1
s1 p2 o2
s2 p1 o2
s2 p1 o3
s3 p1 o2

你用?s分组,然后你将这些结果分成如下:

s1
   [ p1 o1 ]
   [ p2 o2 ]

s2 
   [ p1 o2 ]
   [ p1 o3 ]

s3 
   [ p1 o2 ]

对于每个唯一的s值,您仍然有一堆行,每行都提供p和o值。聚合函数在这些串上运行。所以当你做类似的事情时

select ?s (max(?o) as ?oMax) where {
  ?s ?p ?o
}
group by ?s

max 聚合可以在每个束上工作,即在[o1,o2],[o2,o3]和[o2]上,并从每个束产生一个值。像

这样的东西
select  
   (count(?o) as ?numO)
   (max(?numO) as ?oMax) 
group by ?s

没有意义。当你按分组进行分组时,计数在每一组中运行,并且有一些值,所以你可以计算它们。但是 max 也会尝试在每一组内进行操作,但是这些束没有任何绑定?numO来查看。即使你可以使用 count(?o)中的值,每个只有一个,所以 max 会只是回归那个价值。