在 SPARQL 的 BIND 中使用时,VALUES 的位置似乎很重要

Position of VALUES seems to matter when used in BIND in SPARQL

我正在尝试了解 VALUES 在查询中的位置方面的行为。我们的想法是使用它来更轻松地对来自模板的 SPARQL 查询进行参数化。

对于大多数查询,它按预期工作,但我现在 运行 遇到了一个我不理解的情况。给定以下查询:

SELECT * WHERE {

  # Hard coded version: 

  #BIND( (2020 - 2) AS ?year )

  # Works as expected:
  
  #VALUES ?startYear { 2020 }
  #BIND( (?startYear -2 ) AS ?year )

  # Does not work as expected: 
  # Year is "1" in Fuseki, empty in Stardog. The "-2" does not seem to have any effect in that scenario
  BIND( (?startYear -2 ) AS ?year )
  VALUES ?startYear { 2020 }
} 

如评论中所见,最后一个不行。如果 VALUES 在 BIND 之前,一切似乎都符合预期。在 SPARQL 1.1 规范中,有一个示例,其中他们移动了 VALUES,但我找不到对我在这里看到的内容的解释。

当我在 BIND 中使用 VALUES 时,为什么它在查询末尾不起作用?在这种情况下,它在 FILTER 中运行良好。

重要的是 BIND 的位置,而不是 VALUES。 SPARQL 中的 BIND 总是关闭组图模式,即它位于它之前的同一 {} 块中的所有模式之上,请参阅 https://www.w3.org/TR/sparql11-query/#bind

如果您查看 http://www.sparql.org/query-validator.html:

处的查询结构(所谓的“代数”),就会变得很明显
SELECT *
WHERE {  
  VALUES ?startYear { 2020 }
  BIND( (?startYear -2 ) AS ?year )
}

有这个代数:

  9     (extend ((?year (- ?startYear 2)))
 10       (table (vars ?startYear)
 11         (row [?startYear 2020])
 12       ))))

table 是您的 VALUESextend 是您的 BINDBIND 是在 VALUES 之上计算的,因此 ?startYear 在减去 2 时有一个值。

SELECT *
WHERE {  
  BIND( (?startYear -2 ) AS ?year )
  VALUES ?startYear { 2020 }
}

然而,有以下代数:

  9     (join
 10       (extend ((?year (- ?startYear 2)))
 11         (table unit))
 12       (table (vars ?startYear)
 13         (row [?startYear 2020])
 14       ))))

这里块中的 BIND 之前没有任何内容,因此您看到 table unit 作为它的参数(这就是所谓的空组)。它不绑定任何变量,因此 ?startYear 在计算 BIND 时没有值。 BIND 的结果是 thenVALUES 结合,但为时已晚,因为 - 2 已经发生了。

我总是建议使用该在线工具来检查查询的语义。