我在下面有乌龟格式的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" .
Run Code Online (Sandbox Code Playgroud)
而查询是
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 .}.
}
Run Code Online (Sandbox Code Playgroud)
结果是
------------------------
| first | last |
========================
| "Craig" | "Ellis" |
| "Cindy" | "Marshall" |
| "Dick" | "Mutt" |
------------------------
Run Code Online (Sandbox Code Playgroud)
但如果我将查询更改为
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 .
}
Run Code Online (Sandbox Code Playgroud)
结果是
-------------------
| first | last |
===================
| "Dick" | "Mutt" |
-------------------
Run Code Online (Sandbox Code Playgroud)
任何人都能解释导致这种差异的原因 我认为SPARQL查询中的句点与"和"运算符相同.
Pau*_*ihy 11
这个问题很老了,但答案仍然很难理解清楚。感谢SPARQL_Order_Matters ,允许我尝试使用自然英语
当 OPTIONALS 出现在查询开头时,它们要么
当 OPTIONALS 出现在某些语句已经匹配某些数据之后时,它们要么
因此,真正的非明显行为发生在 OPTIONAL 位于第一个并且它匹配一些三元组时。现在所有查询结果都与该 OPTIONAL 的内容匹配。
Rob*_*obV 10
订购在这里很重要
SPARQL查询的语义通过SPARQL代数表示,这里的两个查询产生非常不同的代数.我使用Apache Jena项目提供的SPARQL查询验证器(免责声明 - 我是该项目的提交者)来生成代数.
您的第一个查询产生以下代数:
(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))))))
Run Code Online (Sandbox Code Playgroud)
并且您的第二个查询产生以下代数:
(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))))))
Run Code Online (Sandbox Code Playgroud)
如您所见,查询中的三重模式以不同的顺序出现,运算符也不同.重要的是,您的第二个查询join只保留了双方的兼容解决方案,而第一个查询仅使用leftjoin哪个保留LHS解决方案,如果没有兼容的解决方案.
因此,在第一个查询中,您首先使用a查找内容,ab:lastName然后可选地添加ab:nick或ab:firstName如果存在,因此您将返回数据中的所有人.
在第二个查询中,您首先找到带有a的东西,ab:nick然后可选地添加带有a的东西,ab:firstName然后要求所有东西都有ab:lastName.因此,您只能获得返回姓氏的人.
我认为SPARQL查询中的句点与"和"运算符相同.
不,它只是终止三重模式,并且可以选择性地遵循其他条款(但不要求这样做),它不是"和"运算符.
除非存在或子句暗示了替代连接运算符(例如leftjoin或minus),否则将连接相邻的基本图形模式OPTIONALMINUS
table unit?table unit 是一个特殊的运算符,对应于SPARQL查询中的空图模式.
例如,SELECT * WHERE { }会生成代数(table unit)
它产生一个空行,在SPARQL的语义中意味着它可以连接到任何东西并返回另一个东西,所以实质上它就像一个连接标识.在许多情况下,SPARQL引擎可以简化要删除的代数,table unit因为在大多数情况下它不会影响查询的语义.
在您的第一个查询中,技术上另一个join在运算符table unit和join运算符之间,但在正常连接的情况下,存在table unit将不起作用(因为它是连接标识),因此它可以并且被简化.
但是,使用OPTIONALSPARQL规范要求生成的代数是子句内部事物的左连接,而不管前面的子句.在第二个查询的情况下,在第一个查询之前没有前面的子句OPTIONAL(技术上存在隐含的空图形模式),因此第一个leftjoin生成的子句table unit在其左侧.不同于普通join的table unit在这种情况下要保留,因为语义leftjoin说,如果没有兼容的解决方案形成RHS从LHS的结果将被保留.
我们可以通过一个更简单的查询来说明这一点:
SELECT *
WHERE
{
OPTIONAL { ?s a ?type }
}
Run Code Online (Sandbox Code Playgroud)
产生代数:
(base <http://example/base/>
(leftjoin
(table unit)
(bgp (triple ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type))))
Run Code Online (Sandbox Code Playgroud)