Sparql变量在块内部未绑定的块之外

时间:2015-12-04 09:53:59

标签: variables union sparql

在针对Sesame内存存储的Sparql查询中,我想分离我的查询条件,例如: "患者是男性"从我的查询的其余部分产生查询结果。

让我们考虑一下这个简单的问题:

PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX nci:<http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#>
PREFIX roo: <http://www.cancerdata.org/roo/>

SELECT DISTINCT *
WHERE { 
  ?Patient a nci:C16960 . 
  ?Patient roo:100018 ?gender .
  ?gender a nci:C20197 .
  BIND(bound(?Patient) as ?bound0) .
  { 
    BIND(bound(?Patient) as ?bound1) .
  } 
  UNION { 
    ?Patient a nci:C16960 . 
    BIND(bound(?Patient) as ?bound2) .
  } 
} 

Bound0始终为true(如预期的那样)。 Bound1始终为false,并且Bound2在结果集中根本没有值(有和没有额外的?Patient triple)。

这是否意味着?Patient变量在第一个块中已知,但未绑定,并且在第二个块中根本不存在(即使我再次声明它)?为什么会有区别?

我的目标是首先定义复杂的查询条件,并将结果集减少到只匹配所有条件的患者。然后使用已经减少的?患者来收集输出中请求的所有数据。

提前感谢您的帮助!

修改

为了进一步说明我的意图,这是一个更复杂的查询。我可以用OPTIONAL而不是UNION编写相同的查询。但是当我使用OPTIONAL时,结果集中的行数会保持快速增长,每个OPTIONAL块返回的命中次数也会增加。如果两个块都返回多个匹配,则结果包含hits1 * hits2记录。我认为我可以通过在高级别使用UNION使其更可预测并将其保持在hits1 + hits2中。是否存在显着的性能差异?

SELECT DISTINCT ?Patient ?Gender ?Neoplastic_Process ?MStage ?TStage
WHERE { 
 ?Patient a nci:C16960 . 
     { 
     ?Patient roo:100018 ?Gender . 
     ?Gender a ?GenderType . 
    } 
    UNION { -- SHOULD I USE OPTIONAL HERE INSTEAD (And for the block above?)
     ?Patient roo:100008 ?Neoplastic_Process . 
     ?Neoplastic_Process a ?Neoplastic_ProcessType . 
        OPTIONAL { 
         ?Neoplastic_Process roo:100241 ?MStage . 
         ?MStage a ?MStageType . 
        } 
        OPTIONAL { 
         ?Neoplastic_Process roo:100244 ?TStage . 
         ?TStage a ?TStageType . 
        } 
    } 
}

我想当我使用OPTIONAL来添加到结果集而不是UNION时,我的分离查询条件的问题不起作用,因为它是同一个块的所有部分。

2 个答案:

答案 0 :(得分:5)

SPARQL执行被定义为功能,即。自下而上。以(1+2) * 3表示计算1+2的方式相同,然后*double(1+2)表示计算1+2并传递3,而非{{1}转到1+2

double
计算

然后与

组合(使用连接)
{ 
    BIND(bound(?Patient) as ?bound1) .
}

所以

?Patient a nci:C16960 . 
?Patient roo:100018 ?gender .
?gender a nci:C20197 .

未绑定{ BIND(bound(?Patient) as ?bound1) . }

引擎会分析查询并以不同的方式在内部执行,但前提是它得到相同的结果。

?Patient的不同部分重复较小的模式可能更容易。对于较大的模式,避免重复考虑子SELECT或OPTIONAL来扩展结果。 (问题中的示例看似简化,因此很难说出最佳方法。)

答案 1 :(得分:1)

在编辑完问题后回答。

看看这部分:

    OPTIONAL { 
     ?Neoplastic_Process roo:100241 ?MStage . 
     ?MStage a ?MStageType . 
    } 
    OPTIONAL { 
     ?Neoplastic_Process roo:100244 ?TStage . 
     ?TStage a ?TStageType . 
    }

这将产生所有匹配的?MStage / ?MStageType?TStage / ?TStageType的叉积。

我不知道您的数据的形状,但也许这种简化将是一个步骤:您可以取出SELECT以外的所有内容并简化:

SELECT ?Patient ?Gender ?Neoplastic_Process ?MStage ?TStage WHERE { ?Patient a nci:C16960 . ?Patient roo:100018 ?Gender . ?Patient roo:100008 ?Neoplastic_Process . OPTIONAL { ?Neoplastic_Process roo:100241 ?MStage . } OPTIONAL { ?Neoplastic_Process roo:100244 ?TStage . } } 根据数据的外观,以及?MStage?TStage是否需要两个不同的变量,其他可能是可能的。