Let's use this data:
@prefix example: <http://example.org/> .
example:subject1 example:property example:object1 .
example:subject1 example:property example:object2 .
Without property paths
A query like this produces ?subjects
that have two distinct values for example:property
:
prefix example: <http://example.org/>
select ?subject where {
?subject example:property ?object1, ?object2 .
filter ( ?object1 != ?object2 )
}
--------------------
| subject ? ? ? ? ?|
====================
| example:subject1 |
| example:subject1 |
--------------------
This is pretty much what you've already got, though. To get it down to one result, you can select distinct
:
prefix example: <http://example.org/>
select distinct ?subject where {
?subject example:property ?object1, ?object2 .
filter ( ?object1 != ?object2 )
}
--------------------
| subject ? ? ? ? ?|
====================
| example:subject1 |
--------------------
About property paths
Property paths are a way of expressing chains of properties (forward and backward) without needing to bind all the individual resources along the way, which is especially important if a variable number of edges are to be allowed. You can bind the things at either end of the chain, but not the things in the middle.
The data, graphically, looks like this:
example:object1 ←example:property example:subject →example:property example:object2
If you wanted to select the two objects that are related to some subject, you could use a property path. The path from example:object1
to example:object2
is (^example:property)/example:property
, because you follow an example:property
edge backward to example:subject
, and then follow an example:property
edge forward to example:object2
. If you wanted the objects, but not the subject, you could use the following query:
prefix example: <http://example.org/>
select * where {
?object1 (^example:property)/example:property ?object2 .
filter ( ?object1 != ?object2 )
}
I don't think there's a convenient way to get the subject using a property path. You could do something like
?subject property/^property/property/^property ?subject
to go from ?subject
to some object, then back to something (i.e., not necessarily ?subject
, then out again, and then back to ?subject
, but you wouldn't be getting the guarantees that there are two distinct objects anymore.
The path language for SPARQL property paths is described in section 9.1 Property Path Syntax of the SPARQL 1.1 Query Language recommendation (the W3C standard). Notably, it doesn't include the p{n}
notation that Section 3 Path Language of the earlier working draft did. This means that your pattern
?subject example:property{2} ?object
isn't actually legal SPARQL (though some implementations might support it). However, according to the working drafts, we can still determine what it means. To match this pattern, you'd need data of the form
?subject →example:property [] →example:property ?object
where []
just indicates some arbitrary resource. This isn't the same shape as the data that you've actually got. So even if this syntax were legal in SPARQL 1.1, it wouldn't give you the type of result that you're looking for. In general, the property paths are essentially a type of regular expression for property chains in the data.
Conclusion
While property chains can make some things very nice, and some otherwise impossible things possible (e.g., see my answer to Is it possible to get the position of an element in an RDF Collection in SPARQL?), I don't think that they're appropriate for this case. I think that your best bet, and a rather elegant solution, is:
?subject example:property ?object1, ?object2 .
filter( ?object1 != ?object2 ).
because it most plainly captures the intended query, “find ?subject
s with two distinct values of example:property
.”