23

I need a little help selecting the right triples from my store....

<a> a <type/1> .
<b> a <type/1> .
<c> a <type/1> .
<c> a <type/2> .

i want to select only elements which are type/1 and not type/2

What is the best way to achieve this using a sparql select query?

am looking for omething like:

select ?a where 
{ 
    ?a a <type/1> .
    !{ ?a a <type/2> }
}

Thanks,

:)

significance
  • 4,797
  • 8
  • 38
  • 57

2 Answers2

28

An alternative SPARQL 1.1 solution is to use MINUS e.g.

SELECT ?a
WHERE
{
  ?a a <type/1> .
  MINUS { ?a a <type/2> . }
}

MINUS subtracts solutions that match its triple pattern from the existing matches.

In most cases using FILTER NOT EXISTS { } and MINUS { } are equivalent but beware there are some corner cases where this is not true - see the SPARQL 1.1 specification for some examples of this.

BookOfGreg
  • 3,550
  • 2
  • 42
  • 56
RobV
  • 28,022
  • 11
  • 77
  • 119
15

In SPARQL 1.0 that's a bit tricky:

SELECT ?a WHERE {
    ?a a <type/1>.
    OPTIONAL {
        ?a a ?othertype .
        FILTER (?othertype = <type/2>)
    }
    FILTER (!BOUND(?othertype))
}

The OPTIONAL clause binds ?othertype for any ?a that has <type/2>, and leaves it unbound for any ?a that doesn't have it.

The final FILTER then selects only those rows where ?a was left unbound.

In SPARQL 1.1 it's much easier:

SELECT ?a WHERE {
    ?a a <type/1>.
    FILTER NOT EXISTS { ?a a <type/2> . }
}
RobV
  • 28,022
  • 11
  • 77
  • 119
cygri
  • 9,412
  • 1
  • 25
  • 47
  • Changed your SPARQL 1.1 example to use explicit URI in the `NOT EXISTS` as using a variable would also match the `` triples the first pattern found and result in filtering out all solutions – RobV Aug 17 '11 at 18:47