4

通过DBpedia SPARQL 端点运行这个查询会得到很多结果(institution填充列):

select ?person ?field ?institution where 

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?institution . }
  OPTIONAL { ?person dbpprop:workInstitutions ?institution .}
  ?person dbpprop:field ?field .
} 

但是,添加该行会FILTER(BOUND(?institution))返回一个空结果集:

select ?person ?field ?institution where 

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?institution . }
  OPTIONAL { ?person dbpprop:workInstitutions ?institution .}
  ?person dbpprop:field ?field .
  FILTER(BOUND(?institution))
} 

为什么是这样?我希望第一个查询的所有institution结果都会显示结果,但没有任何结果。

4

3 回答 3

5

快速回答:这是一个 DBpedia/Virtuoso 错误。

Julian Dolby 和 Kavitha Srinivas在幻灯片 7 上的 SPARQL Optionals 简介中明确描述了这种情况,他们在其中使用了一个示例

optional { ?x name ?label }
optional { ?x nick ?label }

根据SPARQL 规范中的6 Include Optional Values ,对于具有name值的个人,我们永远不会看到任何nick值,因为optional模式是关联的。作者在幻灯片 8 中得出结论:

绑定同一个变量的多个 OPTIONAL 子句很少是您想要的。

optional您应该得到匹配的第一部分的结果。这为变量提供了绑定,所以bound(...)应该是真的。因此,我会说 DBpedia 行为是一个错误。

尝试其他实现。

这是一个有趣的行为,我们可以用简单的数据重现它。假设我们有一些这样的数据:

@prefix : <http://stackoverflow.com/q/22478183/1281433/> .

:a :r :x ; :p 2 ; :q 3 .
:b :r :x ; :p 4 ; :q 5 .

然后我们可以使用以下查询并使用 Jena 获得以下结果。我们只得到属性的结果,:p因为optional它是左关联的,所以:p首先覆盖了模式,我们数据中的每个资源都有一个值:p

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p ?v }
  optional { ?x :q ?v }
}
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------

对于耶拿,添加 afilter不会删除任何结果,我认为这是正确的行为,因为?v 它是绑定的。

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p ?v }
  optional { ?x :q ?v }
  filter(bound(?v))
}
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------

工会或财产的救援路径!

上面引用的幻灯片提到您可以union在内部使用optional来获得您正在寻找的结果。使用我提供的数据,这意味着您可以这样做:

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { 
    { ?x :p ?v } union
    { ?x :q ?v }
  }
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------

这没有问题,但是使用属性路径可以使其更加简洁。如果您真正想要的是绑定?v到or属性的值,则可以使用备用属性路径::p:q

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p|:q ?v }
  filter(bound(?v))
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------

当然,如果你在做filter(bound(?v)),那么模式?x :p|:q ?v真的不再是可选的了,所以你应该把它移到查询的主要部分:

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x ; :p|:q ?v 
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------
于 2014-03-18T15:22:45.777 回答
-1

是的,案子应该得到解决。编译后的 SQL 包含两项检查,一项针对来自第一个 OPTIONAL 的 ?institution,一项针对来自第二个 OPTIONAL 的 ?institution。正式正确的编译应该是在其输出上带有过滤器的嵌套子查询或 FITLER (bound (?institution_1) || bound (?institution_2)) 。真正正确的编译器应该报告关于奇怪查询的警告,但 SPARQL 协议不支持警告:|

于 2014-03-24T05:50:29.903 回答
-1

罪魁祸首是OPTIONAL同一变量 ( ?institution) 上的双精度值。可能发生的情况是,恰好一个 OPTIONAL 总是成功,这意味着另一个总是失败 - 所以?institution变量总是绑定而不是绑定:)

例如,您可以通过以下查询解决它:

select ?person ?field ?institution

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?inst . }.
  OPTIONAL { ?person dbpprop:workInstitutions ?insts . }.
  BIND (IF(bound(?inst), ?inst, ?insts) AS ?institution )
  ?person dbpprop:field ?field .
  filter(bound(?institution)).
} 

它检查哪种情况成功并将其绑定到结果变量?institution

于 2014-03-18T12:19:28.420 回答