通过DBpedia SPARQL endpoint运行此查询可获得许多结果(填充了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
个结果的所有结果都显示出来,但没有任何结果。
答案 0 :(得分:6)
在第7张幻灯片的演示文稿An Introduction to SPARQL Optionals by Julian Dolby and Kavitha Srinivas中明确描述了这种情况,其中他们使用了一个示例
optional { ?x name ?label }
optional { ?x nick ?label }
对于价值为name
的个人,我们永远不会看到任何nick
值,因为optional
模式是关联的,根据6 Including Optional Values来自SPARQL规范。作者在第8栏中总结说:
绑定同一变量的多个OPTIONAL子句很少是你想要的。
您应该获得匹配的第一个optional
部分的结果。这为变量提供了绑定,因此bound(...)
应为true。因此,我会说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 |
----------
使用Jena,添加filter
不会删除任何结果,我认为这是正确的行为,因为?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
绑定到 :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 |
----------
答案 1 :(得分:0)
罪魁祸首是同一个变量(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
。
答案 2 :(得分:-1)
是的,应该修复案件。编译后的SQL包含两个检查,一个用于来自第一个OPTIONAL的机构,另一个用于来自第二个OPTIONAL的机构。正式适当的编译应该是嵌套的子查询,在其输出上有一个过滤器,或者是FITLER(绑定(?institution_1)|| bound(?institution_2))。真正合适的编译器应报告有关奇怪查询的警告,但SPARQL协议不支持警告:|