How do I get intersection-like behavior with SPARQL 1.1 VALUES?
Using 1.1 SPARQL values , the following query returns all predicates using the Einstein or Knuth the object (together with their labels).
PREFIX dbp: <http://dbpedia.org/resource/>
SELECT DISTINCT ?sub ?outpred ?label
{
VALUES ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
?sub ?outpred [] .
?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
Is it possible to use this value function to detect intersection rather than union of predicates? Or am I misunderstanding what's for the values ?
EDIT: Clarification
For a simplified example, let's say there are the following triplets:
<Einstein> <influenced> <John>
<Einstein> <influenced> <Knuth>
<Einstein> <born> <Mars>
<Einstein> <died> <Los Angeles>
<Knuth> <influenced> <Kirby>
<Knuth> <born> <Mars>
<Knuth> <wrote> <TAOCP>
<Knuth> <drove> <Truck>
The "union" I get is all unique predicates tied to any subject (the line is split for clarity):
| ?sub | ?pred |
-------------------------
<Einstein> <influenced>
<Knuth> <influenced>
<Einstein> <born>
<Knuth> <born>
<Einstein> <died>
<Knuth> <wrote>
<Knuth> <drove>
The "intersection" I got is all the unique predicates common to both items:
| ?sub | ?pred |
-------------------------
<Einstein> <influenced>
<Knuth> <influenced>
<Einstein> <born>
<Knuth> <born>
source to share
Solutions
You can use a query like this. The trick is to group using a predicate and only accept those predicates for which there are exactly two subjects (Einstein and Knuth).
select distinct ?outpred ?label
{
values ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
?sub ?outpred [] .
?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
group by ?outpred ?label
having count(distinct ?sub) = 2
Of course, this requires getting all the data you need to combine, and then compressing it. I don't expect this to be a big problem, but if it is (for example, if you are trying to traverse a lot of items), you can also just list the items separately:
select distinct ?outpred ?label
{
dbp:Albert_Einstein ?outpred [].
dbp:Donald_Knuth ?outpred [].
?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
Discussion
Is it possible to use this VALUES function to open intersection rather than union of predicates? Or am I not understanding what VALUES are meant for?
The values โโare just another set of bindings that connect to other bindings, so it cannot do the intersection for you the way you would like it to. However, doing the "intersection" of the sort you are looking for here is not too difficult:
select distinct ?outpred ?label
{
dbp:Albert_Einstein ?outpred [] .
dbp:Donald_Knuth ?outpred [] .
?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
Now, having said that there can be a lot of ternary patterns to write, so you might need some sort of query where the only thing you need to change is a list of values. You can specify values โโand then group by property and label (i.e. Variables with no values) and just take those solutions for which count(distinct ?sub)
is the number of values โโyou specify. For example:.
select distinct ?outpred ?label
{
values ?sub { dbp:Albert_Einstein dbp:Donald_Knuth }
?sub ?outpred [] .
?outpred <http://www.w3.org/2000/01/rdf-schema#label> ?label .
}
group by ?outpre ?label
having count(distinct ?sub) = 2
Thus, to get count(distinct ?sub)
equal to 2, you must have matched ?sub ?outpred []
for ?sub = Einstein
and ?sub = Knuth
.
Approach check
We can use the DBpedia endpoint to work with them. First, a simplified query:
select distinct ?s ?p where {
values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
?s ?p []
}
s p
http://dbpedia.org/resource/Albert_Einstein http://www.w3.org/1999/02/22-rdf-syntax-ns#type
http://dbpedia.org/resource/Donald_Knuth http://www.w3.org/1999/02/22-rdf-syntax-ns#type
http://dbpedia.org/resource/Albert_Einstein http://www.w3.org/2002/07/owl#sameAs
http://dbpedia.org/resource/Donald_Knuth http://www.w3.org/2002/07/owl#sameAs
โฎ โฎ
Now there is no point in asking for an intersection while we are still choosing ? s , because Einstein & ne; Knut, so there never was a crossroads. But can we take the intersection on ? P . Here's a query that gets all properties for which both values โโare valid:
select distinct ?p where {
dbpedia:Albert_Einstein ?p [] .
dbpedia:Donald_Knuth ?p []
}
A similar query calculates the results for us:
select (count(distinct ?p) as ?np) where {
dbpedia:Albert_Einstein ?p [] .
dbpedia:Donald_Knuth ?p [] .
}
There are 45 properties that both have.
Request for -
select distinct ?p where {
values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
?s ?p []
}
group by ?p
having count(?s) = 2
Now let's make sure the other approach gets the same results:
select (count(*) as ?np) where {
select distinct ?p where {
values ?s { dbpedia:Albert_Einstein dbpedia:Donald_Knuth }
?s ?p []
}
group by ?p
having count(distinct ?s) >= 2
}
This also returns 45, so we can see that we are getting the same results.
source to share