Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top