SPARQL 将 MAX 应用于聚合值

SPARQL apply MAX on a value of aggregation

我有这个查询:

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。否则,我会做一个外部 select 我可以获得最大值,但我需要其中三个,这就是我问的原因,因为我自己做不到

更新 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
   }
}
}

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

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

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

您需要完全理解 group by 的作用。 where 部分中的三元组提供了一堆结果行。例如,在

这样的查询中
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

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