I have a SparQL query which first gets me the subjects with one of two predicates.
Then, I group them by a third predicate (that can also be blank) and count the grouped contained subjects.
How (if possible) can I do this without nestation?
My Query currently looks like this:
SELECT ?d (COUNT(?a) AS ?aCount)
WHERE{
SELECT ?d ?a
WHERE {
?a ?b ?c
FILTER (?b=:x||?b=:y)
OPTIONAL {?a :z ?d}
}
GROUP BY ?a ?d
}
GROUP BY ?d
This works, as far as I know, but is with nestation.
Thanks!
Related
I’m new to query languages and linked data so thanks a lot for the help. I also have a similar question about sparql on wikidata
Wikidata sparql query returns 0 result
I would like to look up all the art movements in dbpedia with the associated artists (associated with the movement -peopleNam, famous for the movement-famousName, influence the movement-influenceName) here is my query with lots of redundant prefix (that I could not enter because of the amount of links)
SELECT ?movementName ?famousName ?peopleName ?influenceName
WHERE {
?m dc:subject <http://dbpedia.org/resource/Category:Art_movements> .
?m rdfs:label ?movementName .
FILTER(LANG(?movementName) = "en")
?m dbp:knownFor ?a .
?a rdfs:label ?famousName .
FILTER(LANG(?famousName) = "en")
?m dbp:movement ?b .
?b rdfs:label ?peopleName .
FILTER(LANG(?peopleName) = "en")
?m dbp:influencedBy ?d .
?d rdfs:label ?influenceName .
FILTER(LANG(?influenceName) = "en")
}'
When I run the query with only the movement name I get 235 results but whenever I add any other artist name, I get 0 result. Could you show me what went wrong?
A similar query is done in wikidata with some encouraging results but I haven’t tried to match the two sources yet.
Thanks
I am posing a Sparql query to Dbpedia endpoint with property paths:
select (COUNT(distinct ?s2) AS ?count) WHERE{
?s2 skos:broader{0,2} dbc:Countries_in_Europe
}
I want to pose the same query without property paths:
select (COUNT(distinct ?s2) AS ?count) (COUNT(distinct ?s1) AS ?count1) WHERE{
?s2 skos:broader dbc:Countries_in_Europe.
?s1 skos:broader ?s2.
}
I have two questions:
Is it possible to get ?s1+?s2 for the second query?
For the second query, I expect the sum of the count numbers +1 (dbc:Countries_in_Europe) should be the same with the first query. But they are not. What is wrong?
Thanks in advance.
You're using non-standard SPARQL, i.e. restricting the depth did not make it to the final version, see the W3C specs
I guess the first query is supposed to returns sub-categories of the given one up to a depth 2, right? Your second query doesn't do the same. You have to use a UNION of each distance, i.e. one for the direct sub-categories, and one for the other levels.
SELECT (COUNT(distinct ?s) AS ?count) WHERE {
{
?s skos:broader dbc:Countries_in_Europe
} UNION {
?s1 skos:broader dbc:Countries_in_Europe.
?s skos:broader ?s1
}
}
Note, in your first query you used {0,2} which means due to 0 distance the category dbc:Countries_in_Europe itself is also part of the result. If you need it, you should add +1 to the result of the second query.
Update
As per #JohuaTaylor's comment below, a more compact syntax would be
SELECT (COUNT(distinct ?s) AS ?count) WHERE {
?s skos:broader/skos:broader? dbc:Countries_in_Europe
}
I wrote this query and return list of couples and particular condition. ( in http://live.dbpedia.org/sparql)
SELECT DISTINCT ?actor ?person2 ?cnt
WHERE
{
{
select DISTINCT ?actor ?person2 (count (?film) as ?cnt)
where {
?film dbo:starring ?actor .
?actor dbo:spouse ?person2.
?film dbo:starring ?person2.
}
order by ?actor
}
FILTER (?cnt >9)
}
Problem is that some rows is duplicate.
example:
http://dbpedia.org/resource/George_Burns http://dbpedia.org/resource/Gracie_Allen 12
http://dbpedia.org/resource/Gracie_Allen http://dbpedia.org/resource/George_Burns 12
how to remove these duplications?
I added gender to ?actor but it damage current result.
Natan Cox's answer shows the typical way to exclude these kind of pseudo-duplicates. The results aren't actually duplicates, because in one, e.g., George Burns is the ?actor, and in the other he is the ?person2. In many cases, you can add a filter to require that the two things are ordered, and that will remove the duplicate cases. E.g., when you have data like:
:a :likes :b .
:a :likes :c .
and you search for
select ?x ?y where {
:a :likes ?x, ?y .
}
you can add filter(?x < ?y) to enforce an ordering between the between ?x and ?y which will remove these pseudo-duplicates. However, in this case, it's a bit trickier, since ?actor and ?person2 aren't found using the same critera. If DBpedia contains
:PersonB dbo:spouse :PersonA
but not
:PersonA dbo:spouse :PersonB
then the simple filter won't work, because you'll never find the triple where the subject PersonA is less than the object PersonB. So in this case, you also need to modify your query a bit to make the criteria symmetric:
select distinct ?actor ?spouse (count(?film) as ?count) {
?film dbo:starring ?actor, ?spouse .
?actor dbo:spouse|^dbo:spouse ?spouse .
filter(?actor < ?spouse)
}
group by ?actor ?spouse
having (count(?film) > 9)
order by ?actor
(This query also shows that you don't need a subquery here, you can use having to "filter" on aggregate values.) But the important part is using the property path dbo:spouse|^dbo:spouse to find a value for ?spouse such that either ?actor dbo:spouse ?spouse or ?spouse dbo:spouse ?actor. This makes the relationship symmetric, so that you're guaranteed to get all the pairs, even if the relationship is only declared in one direction.
It is not actual duplicates of course since you can look at it from both ways. The way to fix it if you want to is to add a filter. It is a bit of a dirty hack but it only takes on of the 2 rows that are the "same".
SELECT DISTINCT ?actor ?person2 ?cnt
WHERE
{
{
select DISTINCT ?actor ?person2 (count (?film) as ?cnt)
where {
?film dbo:starring ?actor .
?actor dbo:spouse ?person2.
?film dbo:starring ?person2.
FILTER (?actor < ?person2)
}
order by ?actor
}
FILTER (?cnt >9)
}
Consider we have these two topics:
http://dbpedia.org/page/Jason_Furman
and
http://dbpedia.org/page/London
For the first topic, Jason Furman, we can see on the property almaMater that he went to:
http://dbpedia.org/page/London_School_of_Economics
And looking at London School of Economics we see that it has London as value of the city property.
So my question is:
If we have two topics, A and B, how can we find property values of A that has topic B in any of it's properties?
select distinct ?a ?p ?y ?q ?b where {
values ?a { dbpedia:Jason_Furman }
values ?b { dbpedia:London }
?a ?p ?y .
?y ?q ?b .
}
SPARQL results
(Note that there are two results because there are two such properties: dbpprop:almaMater and dbpedia-owl:almaMater.)
For example,there is one simple select sparql query:
SELECT * Where
{
CT:A skos:broader ?A.
CT:B skos:broader ?B.
FILTER(?A=?B)
}
With the FILTER,it is easy to select the objects that equal to each others.
But when there are even more triples to match ,for example,from CT:A skos:broader ?A to CT:Z skos:broader ?Z,how can I filter those meet ?A=?B=?C=....?Z?
Wish to make it clear.
I think your query should be written as
select ?a where { ct:a skos:broader ?a. ct:b skos:broader ?a }
which means that you want to find an ?a whose the value of skos:broader for both ct:a and ct:b. If you want to make the equivalent for all ct:a, ct:b, ... ct:z then you just repeat the pattern:
select ?a where { ct:a skos:broader ?a. ct:b skos:broader ?a. ct:c skos:broader ?a ... ct:z skos:broader ?a }