In the following SPARQL query, I'm not sure how to use if
to bind one of two strings to the variable ?result
. I heard that there are concepts of “in scope” and “out of scope,” but I don't really see the difference. I've also tried putting the if
clause in the select
line, but it didn't work either. How can I fix this query to bind ?result
to one of the two strings based on the condition?
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)) .
}
The if
operator in SPARQL isn't a statement as it sometimes is in a programming language, but rather is an "function form" for creating an expression (with special evaluation semantics). The value of if(test,a,b)
is a
if test
is true, and b
if test
is false. As the documentation says:
17.4.1.2 IF
rdfTerm IF (expression1, expression2, expression3)
The
IF
function form evaluates the first argument, interprets it as a effective boolean value, then returns the value ofexpression2
if the EBV is true, otherwise it returns the value ofexpression3
. Only one of expression2 and expression3 is evaluated. If evaluating the first argument raises an error, then an error is raised for the evaluation of the IF expression.Examples: Suppose ?x = 2, ?z = 0 and ?y is not bound in some query solution:
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
So, if
isn't a statement like it might be in a programming language, but it's simply a function (though lazily evaluated) that takes three arguments and returns a value. SPARQL is a query language, and doesn't have statements that get executed; it's a query language for matching patterns in a graph and binding variables to values. So if
is a function, and it just so happens that if the first argument is true, then it returns the second argument, otherwise it returns the third. In general, you'd bind the value of a function to a variable with
bind( function(args...) as ?variable )
and this case is no different. You'd call the if
function and bind its result to a variable with
bind( if(condition,then,else) as ?result )
In your case, this means that you would use the following query. I've added some newlines to help the readability, but they're not necessary. Integers in a SPARQL query are shorthand for a literal with type xsd:integer
, so I've also used (thanks to RobV's comment) 0
instead of "0"^^xsd:integer
. (See 2.3.2 Matching Literals with Numeric Types.)
bind(if(?var = 0,
" *"^^xsd:string,
""^^xsd:string )
as ?result)
If we actually want to shorten this even more, then we can use xsd:string
as a constructor, and do (see 17.5 XPath Constructor Functions):
bind(xsd:string(if(?var = 0," *", "")) as ?result)
This might seem a little bit odd at first if you're used to doing things like
String result;
if ( var == 0 ) {
result = "case 1";
}
else {
result = "case 2";
}
but many language actually provide a ternary operator that lets you do the much shorter
String result = (var == 0) ? "case 1" : "case 2";
instead. This is the functionality you're getting with SPARQL.