SPARQL 限制变量的每个值的结果

SPARQL limit the result for each value of a varible

这是重现问题所需的最少数据

@prefix : <http://example.org/rs#>
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

:artist1 rdf:type :Artist .
:artist2 rdf:type :Artist .
:artist3 rdf:type :Artist .
:en rdf:type :Language .
:it rdf:type :Language .
:gr rdf:type :Language .

:c1
    rdf:type :CountableClass ;
    :appliedOnClass :Artist ;
    :appliedOnProperty :hasArtist
.

:c2
    rdf:type :CountableClass ;
    :appliedOnClass :Language ;
    :appliedOnProperty :hasLanguage
.

:i1
    rdf:type :RecommendableClass ;
    :hasArtist :artist1 ;
    :hasLanguage :en
.

:i2
    rdf:type :RecommendableClass ;
    :hasArtist :artist1 ;
    :hasLanguage :en
.


:i3
    rdf:type :RecommendableClass;
    :hasArtist :artist1 ;
    :hasLanguage :it
.

:i4
    rdf:type :RecommendableClass;
    :hasArtist :artist2 ;
    :hasLanguage :en
.


:i5
    rdf:type :RecommendableClass;
    :hasArtist :artist2 ;
    :hasLanguage :it
.

:i6
    rdf:type :RecommendableClass;
    :hasArtist :artist3 ;
    :hasLanguage :gr
.


:ania :likes :i1 .
:ania :likes :i3 .
:ania :likes :i4 .

这是我的查询

PREFIX  :     <http://example.org/rs#>
PREFIX  rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX  rs:   <http://spektrum.ctu.cz/ontologies/radio-spectrum#>

SELECT  ?item ?count ?value
WHERE
  { ?item rdf:type :RecommendableClass
    { SELECT  ?countableProperty ?value (count(*) AS ?count)
      WHERE
        { VALUES ?user { :ania }
          VALUES ?countableConfiguration { :c1 }
          ?user :likes ?x .
          ?countableConfiguration :appliedOnProperty ?countableProperty .
          ?countableConfiguration :appliedOnClass ?countableClass .
          ?x ?countableProperty ?value .
          ?value rdf:type ?countableClass
        }
      GROUP BY ?countableProperty ?value
      ORDER BY DESC(?count)
      LIMIT   3
    }
    FILTER NOT EXISTS {?user :likes ?item}
  }

这是结果:

如您所见,有三个项目的值为 artist1,另外三个项目的值为 artist2

有什么办法可以将每个结果限制为 2 个

首先是一些最小的数据,有三位艺术家,每人有一些项目。我总是强调 Stack Overflow 上的最少数据这一点,因为它对于隔离问题很重要。在这种情况下,您仍然提供了一个相对较大的查询和我们需要的更多数据。由于我们知道问题在于如何对每个与多个项目相关的艺术家进行分组,因此这里需要的所有数据都是与多个项目相关的一些艺术家。然后我们可以很容易地检索它们,并很容易地对它们进行分组。

@prefix : <urn:ex:> .

:artist1 :p :a1, :a2, :a3, :a4 .
:artist2 :p :b2, :b2, :b3, :b4, :b5 .
:artist3 :p :c2 .

现在,您可以 select 艺术家及其项目,并且可以为每个项目确定一个索引。此方法检查每个项目有多少 other 项小于等于它(总是至少有一个等于它(本身),所以计数基本上是 1-基于索引)。

prefix : <urn:ex:>

select ?artist ?item (count(?item_) as ?pos){
  ?artist :p ?item_, ?item .
  filter (str(?item_) <= str(?item))
}
group by ?artist ?item
-------------------------
| artist   | item | pos |
=========================
| :artist1 | :a1  | 1   |
| :artist1 | :a2  | 2   |
| :artist1 | :a3  | 3   |
| :artist1 | :a4  | 4   |
| :artist2 | :b2  | 1   |
| :artist2 | :b3  | 2   |
| :artist2 | :b4  | 3   |
| :artist2 | :b5  | 4   |
| :artist3 | :c2  | 1   |
-------------------------

现在您可以使用 having 来过滤位置,这样您最多可以为每个艺术家获得两个:

prefix : <urn:ex:>

select ?artist ?item {
  ?artist :p ?item_, ?item .
  filter (str(?item_) <= str(?item))
}
group by ?artist ?item
having (count(?item_) < 3)
-------------------
| artist   | item |
===================
| :artist1 | :a1  |
| :artist1 | :a2  |
| :artist2 | :b2  |
| :artist2 | :b3  |
| :artist3 | :c2  |
-------------------

参考资料

在 SPARQL 中执行 "n per each x" 查询是一种挑战,目前还没有很好的解决方案。一些可能有帮助的相关阅读(一定要查看对这些问题和答案的评论)包括:

  • SPARQL using subquery with limit(带限制的子查询有时会有帮助)
  • How to select first N row of each group(我认为是规范问题,但没有答案,因为没有通用答案)
  • (最近的问题有 "hack" 答案)