SPARQL可选查询

我在下面有乌龟格式的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查询中的句点与“和”运算符相同.

订购在这里很重要

SPARQL查询的语义通过SPARQL代数表示,这里的两个查询产生非常不同的代数.我使用Apache Jena项目提供的SPARQL Query Validator(免责声明 – 我是该项目的提交者)来生成代数.

您的第一个查询产生以下代数:

(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))))))

如您所见,查询中的三重模式以不同的顺序出现,运算符也不同.重要的是,您的第二个查询具有仅保留来自双方的兼容解决方案的连接,而第一个查询仅使用leftjoin,如果没有兼容的解决方案,则保留LHS解决方案.

因此,在第一个查询中,您首先使用ab:lastName查找内容,然后可选地添加ab:nick或ab:firstName(如果存在),因此您将返回所有数据中的人员.

在第二个查询中,您首先使用ab:nick查找内容,然后在要求所有内容都包含ab:lastName之前,可以选择使用ab:firstName添加内容.因此,您只能获得返回姓氏的人.

I thought the period in SPARQL query is the same as “and” operator.

不,它只是终止三重模式,并且可以选择性地遵循其他条款(但不要求这样做),它不是“和”运算符.

相邻的基本图形模式是连接的,除非存在可选或MINUS子句隐含了替代连接运算符(例如,leftjoin或minus)

编辑 – 什么是表格单位?

table unit是一个特殊的运算符,对应于SPARQL查询中的空图模式.

例如SELECT * WHERE {}将产生代数(表单位)

它产生一个空行,在SPARQL的语义中意味着它可以连接到任何东西并返回另一个东西,所以实质上它就像一个连接标识.在许多情况下,SPARQL引擎可以简化代数以删除表单元,因为在大多数情况下它不会影响查询的语义.

在您的第一个查询中,技术上在表单元和连接运算符之间存在另一个连接,但是在正常连接的情况下,表单元的存在将不起作用(因为它是连接标识),因此它可以并且被简化.

但是,对于OPTIONAL,SPARQL规范要求生成的代数是子句内部事物的左连接,而不管前面的子句.在第二个查询的情况下,在第一个可选项之前没有前面的子句(技术上存在隐含的空图形模式),因此生成的第一个leftjoin在其左侧具有表单元.与普通连接不同,在这种情况下必须保留表单元,因为左连接的语义表示如果RHS没有兼容的解决方案,则保留LHS的结果.

我们可以通过一个更简单的查询来说明这一点:

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))))
本站公众号
   欢迎关注本站公众号,获取更多程序园信息
开发小院