拍下这张图:
:thing1 a :Foo ;
:has :A ;
:has :B .
:thing2 a :Foo ;
:has :B ;
:has :A .
:thing3 a :Foo ;
:has :A ;
:has :B ;
:has :C .
我想选择:thing1
和:thing2
,但不 :thing3
。
这是我编写的SPARQL查询。有更好的方法吗?
SELECT ?foo WHERE {
?foo a :Foo ;
:has :A ;
:has :B .
MINUS {
?foo a :Foo ;
:has :A ;
:has :B ;
:has ?anythingElse .
FILTER(?anythingElse != :A && ?anythingElse != :B)
}
}
答案 0 :(得分:3)
MINUS的另一种选择是FILTER NOT EXISTS:
SELECT ?foo WHERE {
?foo a :Foo ;
:has :A, :B .
FILTER NOT EXISTS {
?foo :has ?other .
FILTER (?other NOT IN (:A, :B))
}
}
松散地说,找到所有?foo:A和:B,然后检查他们没有其他:有价值。
在执行效率方面,有一些优化可以将一些MINUS模式转换为FILTER NOT EXISTS,反之亦然,并且还有共享子模式的可能性。
如果没有优化器那么聪明,FILTER NOT EXISTS可能会更快,因为"?foo a:Foo; ;有:A,:B。"不重复,FILTER只考虑已通过"?foo a:Foo的项目; ;有:A,:B。"。
当所有效果(包括缓存)结合在一起时,只有一种方法可以知道哪些是真实数据。
答案 1 :(得分:0)
您可以使用NOT IN
运算符而不是布尔表达式来执行此操作,如果将MINUS
子句替换为{{1},则无需重复三个三元模式}子句:
FILTER NOT EXISTS
我怀疑性能会有显着差异,但查询更短更容易阅读。