4

使用 SPARQL 1.1 的values,以下查询返回所有以EinsteinKnuth作为主语的谓词(连同它们的标签)。

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 结果

是否可以使用此功能来公开交集而不是谓词的并集?还是我误解了价值观的用途?

编辑:澄清

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

<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>
4

1 回答 1

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 功能来公开交集而不是谓词的联合?还是我误解了 VALUES 的用途?

Values 本质上是与其他绑定连接的另一组绑定,因此它不能以您想要的方式为您做交集。然而,做一个你在这里寻找的那种“交叉点”并不难:

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)您指定的值数量的解决方案。例如:

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 结果

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
⋮                                            ⋮

现在,在我们仍在选择?s时请求交叉点是没有意义的,因为 Einstein ≠ Knuth,所以永远不会有任何交叉点。但是我们可以在?p上取一个交集。这是一个查询,它获取两者都有值的所有属性:

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

SPARQL 结果

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

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,所以我们看到我们得到了相同的结果。

于 2014-11-24T13:07:47.267 回答