Standard SPARQL can perform negation using the idiom of
OPTIONAL
/!BOUND
. It is inconvenient and can be hard to use as
complexity increases. ARQ supports additional operators for
negation.
The EXISTS
and NOT EXISTS
are now legal SPARQL 1.1 when used inside a FILTER
,
they may be used as bare graph patterns only when Syntax.syntaxARQ
is used
# Names of people who have not stated that they know anyone PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . OPTIONAL { ?x foaf:knows ?who } . FILTER (!BOUND(?who)) }
In ARQ, there is the NOT EXISTS
operator (UNSAID
is an alias
for NOT EXISTS
) which acts at the point in the query where it is
written. It does not bind any variables but variables aready boudn
in the query will have their bound value.
# Names of people who have not stated that they know anyone PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . NOT EXISTS { ?x foaf:knows ?who } }
There is also an EXISTS
operator.
# Names of people where it is stated that they know at least one other person. PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . EXISTS { ?x foaf:knows ?who . FILTER(?who != ?x) } }
In this example, the pattern is a little more complex. Any graph
pattern is allowed although use of OPTIONAL
is pointless (which
will always match, possible with no additional results).
NOT EXISTS
and EXISTS
can also be used in FILTER
expressions.
In SPARQL, FILTER
expressions act over the whole of the basic
graph pattern in which they occur.
# Names of people who have not stated that they know anyone PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . FILTER (NOT EXISTS { ?x foaf:knows ?who }) }
A note of caution:
PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . FILTER (NOT EXISTS { ?x foaf:knows ?y }) ?x foaf:knows ?who }
is the same as (it's a single basic graph pattern - the filter does not break it in two):
PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?x foaf:givenName ?name . ?x foaf:knows ?y . FILTER (NOT EXISTS { ?x foaf:knows ?who }) }
and the FILTER
will always be false ({ ?x foaf:knows ?y }
must
have matched to get to this point in the query and useing ?who
instead makes no difference).