“or” in a SPARQL query

2020-05-25 06:04发布

问题:

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?

回答1:

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.
}


回答2:

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 .
     }
  }
}