4

I am getting comfortable writing regular queries in SPARQL, but I'm still having trouble with fancier stuff. My latest problem is trying to select everything except stuff that matches the where clause. For instance, say I want to find all the husbands who like a car color that their wife doesn't like (I'm working on a proprietary model, so excuse the example and just trust that it makes sense in the real model).

I might have:

<bob> <spouse> <alice>
<bob> <likes> <red>
<alice> <likes> <red>
<carl> <spouse> <dorothy>
<carl> <likes> <blue>
<dorothy> <likes> <yellow>
<eric> <spouse> <fannie>
<eric> <likes> <black>

What's the query that selects carl and eric, but not bob? Bonus points if you can select blue and black in the same query. Selecting bob would be simply:

select ?husband ?color where {?husband <spouse> ?wife . ?husband <likes> ?color . ?wife <likes> ?color}

What I'm looking for is:

select ?husband ?color where {?husband <spouse> ?wife . ?husband <likes> ?color . NOT (?wife <likes> ?color)}

but obviously that's wrong. So what's right?

Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
PlexLuthor
  • 578
  • 2
  • 8
  • 16

2 Answers2

4

There is a simpler and more natural way to do it in SPARQL 1.1 (but it's equivalent to the OPTIONAL/BOUND solution):

SELECT ?husband ?color 
WHERE {
    ?husband <spouse> ?wife .
    ?husband <likes> ?color .
    FILTER NOT EXISTS {?wife <likes> ?color}
}
Antoine Zimmermann
  • 5,314
  • 18
  • 36
4

One correct answer I found through other sources is something like this:

SELECT ?husband ?color 
WHERE {
    ?husband <spouse> ?wife .
    ?husband <likes> ?color .
    OPTIONAL {
        ?wife <likes> ?wifecolor
        FILTER (?wifecolor = ?color)
    }
    FILTER (!BOUND(?wifecolor))
}

It at least works for eric, but I haven't test carl.

Nermin
  • 749
  • 7
  • 17
PlexLuthor
  • 578
  • 2
  • 8
  • 16