我在下面的
中有乌龟格式的RDF @prefix ab: <http://learningsparql.com/ns/addressbook#> .
@prefix d: <http://learningsparql.com/ns/data#> .
d:i0432 ab:firstName "Richard" .
d:i0432 ab:lastName "Mutt" .
d:i0432 ab:homeTel "(229) 276-5135" .
d:i0432 ab:nick "Dick" .
d:i0432 ab:email "richard49@hotmail.com" .
d:i9771 ab:firstName "Cindy" .
d:i9771 ab:lastName "Marshall" .
d:i9771 ab:homeTel "(245) 646-5488" .
d:i9771 ab:email "cindym@gmail.com" .
d:i8301 ab:firstName "Craig" .
d:i8301 ab:lastName "Ellis" .
d:i8301 ab:workTel "(245) 315-5486" .
d:i8301 ab:email "craigellis@yahoo.com" .
d:i8301 ab:email "c.ellis@usairwaysgroup.com" .
,查询是
PREFIX ab: <http://learningsparql.com/ns/addressbook#>
SELECT ?first ?last
WHERE
{
?s ab:lastName ?last .
OPTIONAL {?s ab:nick ?first. }.
OPTIONAL {?s ab:firstName ?first .}.
}
结果是
------------------------
| first | last |
========================
| "Craig" | "Ellis" |
| "Cindy" | "Marshall" |
| "Dick" | "Mutt" |
------------------------
但如果我将查询更改为
PREFIX ab: <http://learningsparql.com/ns/addressbook#>
SELECT ?first ?last
WHERE
{
OPTIONAL {?s ab:nick ?first. }.
OPTIONAL {?s ab:firstName ?first .}.
?s ab:lastName ?last .
}
结果是
-------------------
| first | last |
===================
| "Dick" | "Mutt" |
-------------------
任何人都能解释造成这种差异的原因吗?我认为SPARQL查询中的句点与&#34;和&#34;相同。操作
答案 0 :(得分:10)
这里的排序很重要
SPARQL查询的语义通过SPARQL代数表示,这里的两个查询产生非常不同的代数。我使用SPARQL Query Validator项目提供的Apache Jena(免责声明 - 我是该项目的提交者)来生成代数。
您的第一个查询产生以下代数:
(base <http://example/base/>
(prefix ((ab: <http://learningsparql.com/ns/addressbook#>))
(project (?first ?last)
(leftjoin
(leftjoin
(bgp (triple ?s ab:lastName ?last))
(bgp (triple ?s ab:nick ?first)))
(bgp (triple ?s ab:firstName ?first))))))
您的第二个查询产生以下代数:
(base <http://example/base/>
(prefix ((ab: <http://learningsparql.com/ns/addressbook#>))
(project (?first ?last)
(join
(leftjoin
(leftjoin
(table unit)
(bgp (triple ?s ab:nick ?first)))
(bgp (triple ?s ab:firstName ?first)))
(bgp (triple ?s ab:lastName ?last))))))
正如您所看到的,查询中的三重模式以不同的顺序出现,运算符也不同。重要的是,您的第二个查询的join
仅保留双方的兼容解决方案,而第一个查询仅使用leftjoin
,如果没有兼容的解决方案,则会保留LHS解决方案。
因此,在第一个查询中,您首先会找到包含ab:lastName
的内容,然后可选择添加ab:nick
或ab:firstName
(如果存在),这样您就可以返回所有数据。
在第二个查询中,您首先找到带有ab:nick
的内容,然后在要求所有内容都有ab:firstName
之前,可选择添加ab:lastName
内容。因此,您只能返回姓氏的人。
我认为SPARQL查询中的句点与&#34;和&#34;相同。操作
不,它只是终止三重模式,并且可以选择性地遵循其他条款(但不是必须这样做),它不是&#34;和&#34;操作
相邻的基本图形模式将被连接,除非存在leftjoin
或minus
子句隐含了替代连接运算符(例如OPTIONAL
或MINUS
)
table unit
? table unit
是一个特殊的运算符,对应于SPARQL查询中的空图模式。
例如SELECT * WHERE { }
会产生代数(table unit)
它产生一个空行,在SPARQL的语义中意味着它可以连接到任何东西并返回另一个东西,所以实质上它就像一个连接标识。在许多情况下,SPARQL引擎可以简化代数以删除table unit
,因为在大多数情况下它不会影响查询的语义。
在您的第一个查询中,技术上在join
和table unit
运算符之间存在另一个join
,但在正常联接的情况下,table unit
的存在将无效(因为它是加入标识)所以它可以并且简化了。
然而,对于OPTIONAL
,SPARQL规范要求生成的代数是子句内部事物的左连接,与前面的子句无关。对于第二个查询,在第一个OPTIONAL
之前没有前面的子句(技术上存在隐式空图模式),因此生成的第一个leftjoin
左侧有table unit
侧。与普通join
不同,在这种情况下必须保留table unit
,因为leftjoin
的语义表示如果RHS没有兼容的解决方案,LHS的结果将被保留。< / p>
我们可以用更简单的查询来说明这一点:
SELECT *
WHERE
{
OPTIONAL { ?s a ?type }
}
产生代数:
(base <http://example/base/>
(leftjoin
(table unit)
(bgp (triple ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type))))
答案 1 :(得分:1)
这个问题很旧,但是答案仍然很难理解。感谢SPARQL_Order_Matters
,让我用自然的英语尝试OPTIONALS出现在查询的开头时,它们要么
当某些语句已经与某些数据匹配后出现OPTIONALS时,它们要么
因此,真正的非显而易见的行为是在OPTIONAL首次出现时发生的,并且与某些三元组匹配。现在,所有查询结果都与该OPTIONAL的内容匹配。