如何使用SPARQL 1.1的VALUES获得类似交叉的行为?

时间:2014-11-24 13:00:18

标签: rdf sparql semantic-web dbpedia linked-data

使用SPARQL 1.1的values,以下查询返回所有谓词,其中爱因斯坦 Knuth 作为主题(及其标签)。

PREFIX dbp: <http://dbpedia.org/resource/>

SELECT DISTINCT ?sub ?outpred ?label
{
  VALUES ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
  ?sub ?outpred [] .
  ?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}

SPARQL results

是否可以使用此功能公开谓词的交集而不是 union ?或者我误解了的用途?

编辑:澄清

举一个简单的例子,假设有这些三元组:

<Einstein>  <influenced>    <John>
<Einstein>  <influenced>    <Knuth>
<Einstein>  <born>          <Mars>
<Einstein>  <died>          <Los Angeles>
<Knuth>     <influenced>    <Kirby>
<Knuth>     <born>          <Mars>
<Knuth>     <wrote>         <TAOCP>
<Knuth>     <drove>         <Truck>

我得到的“联合”是所有唯一的谓词附加到任一主题(为清晰起见分开的行):

|  ?sub    |  ?pred     |
-------------------------
<Einstein>  <influenced>
<Knuth>     <influenced>

<Einstein>  <born>
<Knuth>     <born>

<Einstein>  <died>

<Knuth>     <wrote>

<Knuth>     <drove>

我所追求的“交集”是两个主题共有的唯一谓词:

|  ?sub    |  ?pred     |
-------------------------
<Einstein>  <influenced>
<Knuth>     <influenced>

<Einstein>  <born>
<Knuth>     <born>

1 个答案:

答案 0 :(得分:4)

解决方案

您可以使用这样的查询。诀窍是分组谓词,并且只采用那些恰好有两个主题的谓词(爱因斯坦和克努特)。

select distinct ?outpred ?label
{
  values ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
  ?sub ?outpred [] .
  ?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
group by ?outpred ?label
having count(distinct ?sub) = 2

当然,这确实需要检索联合所需的所有数据,然后将其缩小。我不希望这会成为一个很大的问题,但如果是这样的话(例如,如果你正在尝试为许多科目选择交叉点),那么你也可以单独列出这些科目:

select distinct ?outpred ?label
{
  dbp:Albert_Einstein ?outpred [].
  dbp:Donald_Knuth ?outpred [].
  ?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}

讨论

  

是否可以使用此VALUES功能来显示交叉点   而不是谓词的联合?或者我误解了什么   价值是为了什么?

值本质上是另一组与其他绑定连接的绑定,因此它不能按照您喜欢的方式与您进行交集。然而,做一个&#34;十字路口&#34;你在这里寻找的那种方式并不太难:

select distinct ?outpred ?label
{
  dbp:Albert_Einstein ?outpred [] .
  dbp:Donald_Knuth ?outpred [] .
  ?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}

现在,那就是说,这可能是很多三重模式要写,所以你可能想要一些查询,你唯一需要改变的是一个值列表。您可以指定值,然后按属性和标签(即非值变量)进行分组,并采用那些count(distinct ?sub)是您指定的值的解决方案。 E.g:

select distinct ?outpred ?label
{
  values ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
  ?sub ?outpred [] .
  ?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
group by ?outpre ?label
having count(distinct ?sub) = 2

这样,为了使count(distinct ?sub)为2,您必须与 ?sub ?outpred []?sub = Einstein进行?sub = Knuth匹配。

检查方法

我们可以使用DBpedia端点来解决这些问题。首先,简化查询:

select distinct ?s ?p where {
  values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
  ?s ?p []
}

SPARQL results

s                                             p
http://dbpedia.org/resource/Albert_Einstein   http://www.w3.org/1999/02/22-rdf-syntax-ns#type
http://dbpedia.org/resource/Donald_Knuth      http://www.w3.org/1999/02/22-rdf-syntax-ns#type
http://dbpedia.org/resource/Albert_Einstein   http://www.w3.org/2002/07/owl#sameAs
http://dbpedia.org/resource/Donald_Knuth      http://www.w3.org/2002/07/owl#sameAs
⋮                                            ⋮

现在,当我们仍然选择时,要求交叉点是没有意义的,因为爱因斯坦≠Knuth,所以从来没有任何交集。但我们可以在?p 上进行交集。这是一个查询,它获取两个都具有值的所有属性:

select distinct ?p where {
  dbpedia:Albert_Einstein ?p [] .
  dbpedia:Donald_Knuth ?p []
}

SPARQL results

类似的查询会为我们计算结果:

select (count(distinct ?p) as ?np) where {
  dbpedia:Albert_Einstein ?p [] .
  dbpedia:Donald_Knuth ?p [] .
}

他们都有45个属性。

分组查询

select distinct ?p where {
  values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
  ?s ?p []
}
group by ?p
having count(?s) = 2

现在让我们确保其他方法获得相同的结果:

select (count(*) as ?np) where {
  select distinct ?p where {
    values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
    ?s ?p []
  }
  group by ?p
  having count(distinct ?s) >= 2
}

这也返回45,所以我们看到我们得到了相同的结果。