SPARQL 在将 MIN(?date1) 从子查询传递到外部查询时返回空结果,使用 BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
SPARQL returning empty result when passing MIN(?date1) from subquery into outer query, with BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
<此问题现已解决,请参阅 Valerio Cocchi 的评论>
我正在尝试从子查询传递一个变量,该变量采用属于 ?p 的一组日期 ?date1 中的最小日期,并将其传递给外部查询,然后外部查询采用属于 ?date2 的另一个日期? p(每个 ?p 最多可以有 1 个 ?date2)并从 ?date2 中减去 ?minDate 得到一个整数值,表示两者之间的年数。我为此得到一个空白值,即 ?diffDate returns no value.
我使用的是 Fuseki 4.3.2 版。以下是查询示例:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}
以及我得到的那种结果的示例:
|-?p----|----------------?minDate------------|--- --------------?date2------------ |?diffDate|
|<123>|20012-11-22T00:00:00"^^xsd:dateTime|2008-08-18T00:00:00"^^xsd:dateTime| |
我希望 ?diffDate 会给我一个整数值。我是否遗漏了有关子查询在 SPARQL 中的工作原理的一些基本知识?
您似乎遇到了 SPARQL 规范中相当晦涩的部分,即 BIND
的工作原理。
通常 SPARQL 的计算不考虑原子的位置,即
SELECT *
WHERE {
?a :p1 ?b .
?b :p2 ?c .}
与以下查询相同:
SELECT *
WHERE {
?b :p2 ?c .
?a :p1 ?b .}
但是,BIND 是位置依赖的,所以例如:
SELECT *
WHERE {
?a :p1 ?b .
BIND(:john AS ?a)}
不是有效查询,而:
SELECT *
WHERE {
BIND(:john AS ?a)
?a :p1 ?b .
}
完全有效。这同样适用于 BIND
内部使用的变量,这些变量必须在 BIND
出现之前声明。
有关更多信息,请参阅 here。
回到您的问题,您的 BIND
在绑定之前使用 ?minDate
变量,这就是它无法为 ?diffDate
生成值的原因。
这个查询应该可以解决问题:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate) #Put the BIND after all the variables it uses are bound.
}
或者,您可以评估 SELECT
中的差异,如下所示:
SELECT ?p ?minDate ?date2 (YEAR(?minDate) - YEAR(?date2) AS ?diffDate)
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}
<此问题现已解决,请参阅 Valerio Cocchi 的评论>
我正在尝试从子查询传递一个变量,该变量采用属于 ?p 的一组日期 ?date1 中的最小日期,并将其传递给外部查询,然后外部查询采用属于 ?date2 的另一个日期? p(每个 ?p 最多可以有 1 个 ?date2)并从 ?date2 中减去 ?minDate 得到一个整数值,表示两者之间的年数。我为此得到一个空白值,即 ?diffDate returns no value.
我使用的是 Fuseki 4.3.2 版。以下是查询示例:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}
以及我得到的那种结果的示例:
|-?p----|----------------?minDate------------|--- --------------?date2------------ |?diffDate|
|<123>|20012-11-22T00:00:00"^^xsd:dateTime|2008-08-18T00:00:00"^^xsd:dateTime| |
我希望 ?diffDate 会给我一个整数值。我是否遗漏了有关子查询在 SPARQL 中的工作原理的一些基本知识?
您似乎遇到了 SPARQL 规范中相当晦涩的部分,即 BIND
的工作原理。
通常 SPARQL 的计算不考虑原子的位置,即
SELECT *
WHERE {
?a :p1 ?b .
?b :p2 ?c .}
与以下查询相同:
SELECT *
WHERE {
?b :p2 ?c .
?a :p1 ?b .}
但是,BIND 是位置依赖的,所以例如:
SELECT *
WHERE {
?a :p1 ?b .
BIND(:john AS ?a)}
不是有效查询,而:
SELECT *
WHERE {
BIND(:john AS ?a)
?a :p1 ?b .
}
完全有效。这同样适用于 BIND
内部使用的变量,这些变量必须在 BIND
出现之前声明。
有关更多信息,请参阅 here。
回到您的问题,您的 BIND
在绑定之前使用 ?minDate
变量,这就是它无法为 ?diffDate
生成值的原因。
这个查询应该可以解决问题:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate) #Put the BIND after all the variables it uses are bound.
}
或者,您可以评估 SELECT
中的差异,如下所示:
SELECT ?p ?minDate ?date2 (YEAR(?minDate) - YEAR(?date2) AS ?diffDate)
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}