#sparql
Вопрос:
Я пытаюсь понять, как ЗНАЧЕНИЯ ведут себя в отношении позиции в запросе. Идея состоит в том, чтобы использовать это для упрощения параметризации запросов 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 }
}
Как вы можете видеть в комментариях, последнее не работает. Если ЗНАЧЕНИЯ находятся перед ПРИВЯЗКОЙ, все выглядит так, как ожидалось. В спецификации SPARQL 1.1 есть пример, в котором они перемещают ЗНАЧЕНИЯ, но я не могу найти объяснение тому, что я вижу здесь.
Почему это не работает, когда ЗНАЧЕНИЯ находятся в конце запроса, когда я использую его в ПРИВЯЗКЕ? В этом случае он хорошо работает в FILTER.
Комментарии:
1. важная часть содержится в спецификациях для
BIND
: «Использование BIND завершает предыдущий базовый шаблон графа» — это означает, что шаблон графа, включающийBIND
в себя, оценивается передVALUES
предложением. И также обратите внимание, что aVALUES
не помещает привязки во вложенные шаблоны графов. Это не похоже на нажатие фильтра в базах данных. Кстати, то же самое относится и к подзапросам.2. ?год не определен в Fuseki.
Ответ №1:
Важна позиция BIND, а не ЗНАЧЕНИЯ. BIND в SPARQL всегда закрывает шаблон группового графа, т. Е. Он идет поверх всех шаблонов в том же {}
блоке, которые предшествуют ему, см. 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
VALUES
и extend
ваше BIND
. Вычисляется BIND
поверх 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
вычислении. Затем результат привязки соединяется с VALUES
, но слишком поздно, поскольку - 2
это уже произошло.
Я всегда рекомендую использовать этот онлайн-инструмент для проверки семантики ваших запросов.