29

I don't quite understand why in SPARQL they haven't implemented the basic logic operators. However in most of the cases is possible to obtain the same result in a number of way.

The purpose of this question is to have a quick reference for the possible way troughs that can substitute an "or" statement.

Here's what I can think of:

1)UNION

e.g:

SELECT * WHERE
{  { ?s :propA ?o } UNION { ?s :propB ?o }  }

-not often suitable because it can became very verbose because

SELECT * WHERE { 
    { GRAPH ?g {?s ?p ?o. ?o ?pp ?data1}} UNION 
    { GRAPH ?g {?s ?p ?o. ?o ?pp ?data2}}
} 

doesn't work as

SELECT * WHERE { 
    GRAPH ?g {
       ?s ?p ?o. 
       {?o ?pp ?data1} UNION 
       {?o ?pp ?data2} 
    }
 }

(at least not with Stardog)

2)FILTER

e.g:

SELECT * WHERE
    { 
        ?s ?p ?o.
        FILTER (?p = :propA || ?p = :propB )
    }

Any other ideas?

Community
  • 1
  • 1
ffa
  • 557
  • 1
  • 4
  • 12
  • I'm sorry, but what do you mean when you say the first query "don't work as" the second query? Are you expecting those two queries to do the exact same thing? – Jeen Broekstra May 28 '15 at 10:50
  • if `UNION ` would work exactly like a logical-OR the 2 queries would have produced the same result, but of course they don't. I'm sorry that I can't explain myself properly, I'm a sparql newbie and also English is not my mother tongue, thank you for your comprehension and your time. – ffa May 28 '15 at 12:11
  • 1
    @ffa We're getting off on a tangent here I guess, but you are under a misconception that UNION is somehow different from a logical-OR. They are semantically the exact same thing, however. The reason the two queries are different is simply one of scoping. The first query is `((?s ?p ?o ?g) AND (?o ?pp ?data1 ?g)) OR ((?s ?p ?o ?g) AND (?o ?pp ?data2 ?g))`, the second query is `(?s ?p ?o ?g) AND ((?o ?pp ?data1 ?g) OR (?o ?pp ?data2 ?g))`. – Jeen Broekstra May 28 '15 at 18:20
  • 1
    ...and no worries about your English, it's fine, and if I don't understand something you say I just ask you to explain (and I hope you do the same to me) :) – Jeen Broekstra May 28 '15 at 18:27

2 Answers2

43

I'm not entirely sure why you say SPARQL doesn't supply 'the basic logic operators', because your own examples clearly show that it does: it provides logical-OR (||) and logical-AND (&&) as part of FILTER conditions, and disjunctive graph patterns using UNION (of course, conjunctive graph patterns need no special syntax).

Other variations of OR-like constructs are also possible. For queries of the form "this particular value must be one of these possibilities" you can use the set membership operator, IN:

SELECT * 
WHERE { 
    ?s ?p ?o.
    FILTER (?p IN (:propA, :propB, :propC ) )
}

You can also use the VALUES clause for this kind of pattern:

SELECT * 
WHERE {
    VALUES ?p { :propA :propB :propC } 
    ?s ?p ?o.
}

Update I forgot one, perhaps the simplest. For queries such as yours, where you are looking for a few alternatives for a property name, you can actually use a property path expression as well, like so:

SELECT * 
WHERE {
    ?s :propA|:propB|:propC ?o.
}
Jeen Broekstra
  • 20,156
  • 4
  • 43
  • 67
  • I mean that you can use the basic logic operators *only* inside a `FILTER` condition. In my (limited) experience a more comprehensive implementation would have been handy in a lot of situations. The `UNION` statement often is not an option because you can't nest it. Anyway thank you for your precious contribution. – ffa May 28 '15 at 09:56
  • Actually, you can nest `UNION`s just fine. I'd be interested to see a disjunctive graph pattern that you think cannot be expressed using `UNION` - if you have an example can you edit your question to that effect? – Jeen Broekstra May 28 '15 at 09:58
  • yeha, but for example `SELECT * WHERE{ { GRAPH ?g {?s ?p ?o. ?o ?pp ?data1} UNION { GRAPH ?g {?s ?p ?o. ?o ?pp ?data2} } ` don't work as `SELECT * WHERE{ { GRAPH ?g {?s ?p ?o. {?o ?pp ?data1} UNION { ?o ?pp ?data2} } ` (at least with Stardog) – ffa May 28 '15 at 10:05
  • Also not entirely sure what you imagine this "more comprehensive implementation" should look like. Can you give some example of the kind of thing that you'd _like_ to be able to write in SPARQL? – Jeen Broekstra May 28 '15 at 10:05
  • @ffa adding SPARQL queries in comments makes them almost impossible to read - can you instead add these examples to your question so they can be properly formatted? – Jeen Broekstra May 28 '15 at 10:07
  • 1
    @JeenBroekstra: does | work for the object as well? e.g. ?a a :object1|:object2. I have actually tried and it didnt work. But I might have been doing something wrong!!! – msc87 Aug 03 '17 at 13:28
  • 3
    @msc87, no, property path expressions only work for properties. For objects, you will have to use one of the other constructs. – Jeen Broekstra Aug 03 '17 at 22:48
  • Thanks for this explanation - I have tried all three and have discovered some interesting performance implications. With Apache Jena, for example, the property path variant is by far the slowest. Do you have any hint as to why that might be? – Rok Oct 28 '19 at 21:18
4

If you want to trace which predicate lead to which object then this is universal solution for "OR" :

SELECT DISTINCT ?s ?o1 ?o2 
WHERE {
  {
     ?s p1 ?o1 .
     OPTIONAL
     {
        ?s p2 ?o2 .
     }
  } 
  UNION 
  {
     ?s p2 ?o2 .
     OPTIONAL
     {
        ?s p1 ?o1 .
     }
  }
}