3

Let say I have triples of the form

uri:ObjA1 uri:propAA uri:Obj1A .
uri:ObjA1 uri:propAA uri:Obj1B .

uri:ObjA2 uri:propAA uri:Obj1A .
uri:ObjA2 uri:propAA uri:Obj1B .
uri:ObjA2 uri:propAA uri:Obj1C .

Now, what I am trying to do is find all instances that only have values Obj1A and Obj1B for propAA. Basically, the query should return ObjA1 and not ObjA2 because only ObjA1 takes values Obj1A and Obj1B only for propAA. What I have right now is

SELECT * where {
    ?sub uri:propAA uri:Obj1A .
    ?sub uri:propAA uri:Obj1B .
    FILTER NOT EXISTS {
        ?sub uri:propAA ?obj .
        FILTER((?obj != uri:Obj1A) && (?obj != uri:Obj1B)) .
    }
}

Now, this query works. If I don't put the FILTER NOT EXISTS clause, then it returns both ObjA1 and ObjA2. What I am looking for now is to know if there is a better way to write this query? Better would mean, more efficient or more concise (or both).

scotthenninger
  • 3,921
  • 1
  • 15
  • 24
thisisshantzz
  • 1,067
  • 3
  • 13
  • 33

2 Answers2

1

You could shorten things slightly using the NOT IN operator, and also using the , connector to avoid repeating the triple pattern:

SELECT * where {
    ?sub uri:propAA uri:Obj1A, uri:Obj1B .
    FILTER NOT EXISTS {
        ?sub uri:propAA ?obj .
        FILTER(?obj NOT IN (uri:Obj1A, uri:Obj1B))
    }
}

I doubt either change will make a difference, performance-wise, but it is more concise and also (IMHO) a bit easier to read.

FWIW, the double negation here is a classical way to rewrite universal quantification. After all, logically, ∀x P(x) equals ∄x ¬P(x). Since SPARQL has no FORALL operator, you have to make do with NOT EXISTS and a double negation.

Jeen Broekstra
  • 21,642
  • 4
  • 51
  • 73
0

Stated in terms of triple patterns you're looking for a solution for ?sub where values of uri:propAA are both uri:Obj1A and uri:Obj1B. This is basic conjunction in SPARQL:

SELECT * 
WHERE {
   ?sub uri:propAA uri:Obj1A .
   ?sub uri:propAA uri:Obj1B .
}
scotthenninger
  • 3,921
  • 1
  • 15
  • 24
  • I tried this query but it does not work. It does not ignore those instances that have other values for propAA apart from Obj1A and Obj1B. What I am looking for is to get only those instances that have Obj1A and Obj1B as values for propAA. Anything more or less should not be returned. In the example that I gave, ObjA2 should not be returned because apart from Obj1A and Obj1B as values for propAA, it also has Obj1C as a value for propAA. – thisisshantzz Jul 19 '16 at 04:11