Привязка переменной к одному из двух значений с IF?

В следующем запросе SPARQL я не уверен, как использовать if для привязки одной из двух строк к переменной ?result. Я слышал, что есть понятия "по охвату" и "вне сферы действия", но я не вижу разницы. Я также попытался поместить предложение if в строку select, но это тоже не сработало. Как я могу исправить этот запрос, чтобы привязать ?result к одной из двух строк на основе условия?

SELECT ?result
WHERE{
    ?chain rdf:type rdfs:Property .
    ?chain rdfs:domain <http://www.vs.cs.hs-rm.de/ontostor/SVC#MDiskGroup> .
    ?chain rdfs:range <http://www.vs.cs.hs-rm.de/ontostor/SVC#IOgroup> .
    ?this ?chain ?arg .
    ?arg io:id ?var .
    IF(?var = "0"^^xsd:integer,
       BIND("    *"^^xsd:string AS ?result),
       BIND(""^^xsd:string AS ?result)) .
}

Ответ 1

Оператор if в SPARQL не является оператором, поскольку он иногда находится на языке программирования, но является функциональной. выражение. Значение if(test,a,b) равно a, если test истинно, а b, если test - false. Как говорится в документации:

17.4.1.2 IF

rdfTerm  IF (expression1, expression2, expression3)

Форма функции if оценивает первый аргумент, интерпретирует ее как эффективное значение boolean, затем возвращает значение expression2, если EBV истинно, в противном случае оно возвращает значение expression3. Единственный выражения 2 и выражения 3. Если оценивать первый аргумент вызывает ошибку, тогда возникает ошибка для оценки выражения IF.

Примеры: предположим? x = 2,? z = 0 и? y не связаны в некотором запросе Решение:

IF(?x = 2, "yes", "no")     returns "yes"
IF(bound(?y), "yes", "no")  returns "no"
IF(?x=2, "yes", 1/?z)       returns "yes", the expression 1/?z is not evaluated
IF(?x=1, "yes", 1/?z)       raises an error
IF("2" > 1, "yes", "no")    raises an error

Итак, if - это не такой оператор, который может быть на языке программирования, а просто функция, которая принимает три аргумента и возвращает значение. SPARQL - это язык запросов и не имеет операторов, которые выполняются; это язык запросов для сопоставления шаблонов в графе и привязки переменных к значениям. Таким образом, if - это функция, и бывает так, что если первый аргумент имеет значение true, он возвращает второй аргумент, иначе он возвращает третий. В общем случае вы привязываете значение функции к переменной с помощью

bind( function(args...) as ?variable )

и этот случай ничем не отличается. Вы вызываете функцию if и привязываете ее результат к переменной с помощью

bind( if(condition,then,else) as ?result )

В вашем случае это означает, что вы будете использовать следующий запрос. Я добавил некоторые новые строки, чтобы помочь читаемости, но они не нужны. Целые числа в запросе SPARQL являются сокращением для литерала с типом xsd:integer, поэтому я также использовал (спасибо RobV comment) 0 вместо "0"^^xsd:integer. (См. 2.3.2 Согласование литералов с числовыми типами.)

bind(if(?var = 0,
        "    *"^^xsd:string,
        ""^^xsd:string )
     as ?result)

Если мы действительно хотим сократить это еще больше, то мы можем использовать xsd:string в качестве конструктора и делать (см. 17.5 Функции конструктора XPath):

bind(xsd:string(if(?var = 0,"    *", "")) as ?result)

Сначала это может показаться немного странным, если вы привыкли делать такие вещи, как

String result;
if ( var == 0 ) {
  result = "case 1";
}
else {
  result = "case 2";
}

но многие языки фактически предоставляют тернарный оператор, который позволяет вам делать гораздо более короткие

String result = (var == 0) ? "case 1" : "case 2";

вместо этого. Это функциональность, которую вы получаете с помощью SPARQL.