MINUS — remove matching solutions
MINUS { … } removes every solution that agrees with some solution of the MINUS pattern on all the variables they share.
Examples use the sample data.
Example
People without a mailbox:
SELECT * FROM pgrdf.sparql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?p
WHERE { ?p a foaf:Person
MINUS { ?p foaf:mbox ?mbox } }
$$);
-- {"p": "http://example.org/bob"}MINUS is the usual replacement for FILTER NOT EXISTS, which pgRDF does not support. OPTIONAL with FILTER(!BOUND(?v)) is the other (see OPTIONAL).
Matching on more than one variable
A solution is removed only when every shared variable agrees. Here: who knows someone who doesn't know them back?
SELECT * FROM pgrdf.sparql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?a ?b
WHERE { ?a foaf:knows ?b
MINUS { ?b foaf:knows ?a } }
ORDER BY ?a ?b
$$);
-- {"a": "http://example.org/alice", "b": "http://example.org/bob"}
-- {"a": "http://example.org/alice", "b": "http://example.org/carol"}
-- {"a": "http://example.org/bob", "b": "http://example.org/carol"}No shared variables: nothing is removed
If the MINUS pattern shares no variable with the rest of the query, no solution can agree with it, so nothing is removed (SPARQL 1.1 §8.3.2):
SELECT * FROM pgrdf.sparql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?p
WHERE { ?p a foaf:Person
MINUS { ?x foaf:mbox ?y } }
$$);
-- {"p": "http://example.org/carol"}
-- {"p": "http://example.org/bob"}
-- {"p": "http://example.org/alice"}What can go inside MINUS
Triple patterns, optionally wrapped in GRAPH <iri> { … } (see GRAPH). A UNION or a FILTER inside MINUS is refused with 0A000.
Instead of a UNION inside one MINUS, write one MINUS block per alternative:
SELECT * FROM pgrdf.sparql($$
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX ex: <http://example.org/>
SELECT ?p
WHERE { ?p a foaf:Person
MINUS { ?p foaf:mbox ?m }
MINUS { ?p ex:phone ?ph } }
$$);
-- {"p": "http://example.org/bob"}