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 }
Related
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!
I am trying to find all those resources from dbpedia for eg rdf:type person who have same object eg date of birth.?
I thought of doing it with subquery but its definitely not the solution.
Can anyone provide some useful pointer?
From what you describe I think you mean:
prefix dbp: <http://dbpedia.org/property/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
select ?s1 ?s2 ?dob
where {
?s1 a foaf:Person ; dbp:birthDate ?dob . # Find a person, get their dob
?s2 a foaf:Person ; dbp:birthDate ?dob . # Find a person with the same dob
}
Adjust type and predicate to suit.
This will include some redundancy: you will find answers where the subjects are the same ('Napoleon' 'Napoleon') and get answers twice ('Daniel Dennett' 'Neil Kinnock', 'Neil Kinnock' 'Daniel Dennett'). You can remove that with a filter:
filter (?s1 < ?s2)
which just ensures that one comes before the other (however the query engine wants to do that).
prefix dbp: <http://dbpedia.org/property/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
select ?s1 ?s2 ?dob
where {
?s1 a foaf:Person ; dbp:birthDate ?dob .
?s2 a foaf:Person ; dbp:birthDate ?dob .
filter (?s1 < ?s2)
}
See the result
A SPARQL query is basically a set of triple patterns, i.e., a join (logical AND) of queries of the form
?subject ?predicate ?object.
What you need is identical ?object. Considering that you only care about ?subject (?predicate is not of importance), you can perform such a query you by ordering the results depending on ?object. Thus you will see results sharing ?object together.
select ?s ?p ?o where {
?s ?p ?o.
}
order by ?o
If you care about ?predicate as well, you should order the result using it second.
select ?s ?p ?o where {
?s ?p ?o.
}
order by ?o ?p
As those couple of queries may involve too many results as they will retrieve all the results possible. I recommend filtering ?object depending on some specific criteria. For example, to select all ?subject sharing an instance of Person as their ?object, use:
select ?s where {
?s ?p ?o.
{select ?o where{
?o a <http://dbpedia.org/ontology/Person>}
}
}
An alternative solution to the others is using aggregate functions like in this query template
select ?o (count(distinct ?s) as ?cnt) (group_concat(distinct ?s; separator=";") as ?subjects) {
?s a <CLASS> ;
<PREDICATE> ?o .
}
group by ?o
order by desc(count(distinct ?s))
which returns for each object the number of subjects and the list of subject belonging to a class CLASS for a given predicate PREDICATE
For example, asking for the dates of soccer players one could use
prefix dbo: <http://dbpedia.org/ontology/>
select ?date (count(distinct ?s) as ?cnt) (group_concat(distinct ?s; separator=";") as ?subjects) {
?s a dbo:SoccerPlayer ;
dbo:birthDate ?date .
}
group by ?date
order by desc(count(distinct ?s))
select * where {
?person1 a <http://dbpedia.org/ontology/Person>.
?person1 dbo:birthYear ?date.
?person2 a <http://dbpedia.org/ontology/Person>.
?person2 dbo:birthYear ?date
FILTER (?person1 != ?person2)
}
limit 10
Dbpedia will not allow you to execute that query on its public endpoint because it consumes more time that allowed, and you cannot change that time. Nevertheless, there are ways to execute it
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)
}
Is possible to select the "negative" of a sparql query?
For instance, consider the following RDF data, query and desired result:
knowledge base:
#prefix gr:<http://purl.org/goodrelations/v1#>.
#prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>.
:prod_A :hasProp :propA.
:prod_B :hasProp :propB.
:propB rdfs:label "Hello".
:prod_C :hasProp :propC.
:prod_D :hasProp :propD.
Imaginary Query:
PREFIX gr:<http://purl.org/goodrelations/v1#>
SELECT ?prod WHERE
{ !(
?prod ?p ?o.
?o ?p2 ?o2.
) }
Ideal Result:
| ?prod |
|---------|
| :prod_A |
| :prod_C |
| :prod_D |
is there a way through? (i need it for a delete)
I think MINUS is what you are looking for:
PREFIX gr:<http://purl.org/goodrelations/v1#>
SELECT ?prod WHERE
{
?prod ?p ?o.
MINUS { ?o ?p2 ?o2 }
}
It takes the things matched by the left hand side (?prod ?p ?o) and removes any that correspond to items matched by the MINUS pattern.
Note this doesn't give your desired answer because the ?prod ?p ?o pattern matches everything including the linked property (:propB rdfs:label "Hello") that you aren't interested in for your results
To get your desired answer you need to make the first part of the query more specific like so:
PREFIX :<http://example.org/>
PREFIX gr:<http://purl.org/goodrelations/v1#>
SELECT ?prod WHERE
{
?prod :hasProp ?o.
MINUS { ?o ?p2 ?o2 }
}
Here I changed the ?p variable to be the :hasProp constant instead. With this query I get your desired answer.
NB - You didn't define the empty prefix in your example so I invented one to make the query valid and so I could test that it worked
Another way is to use FILTER NOT EXISTS
SELECT ?prod WHERE
{
?prod :hasProp ?o.
FILTER NOT EXISTS { ?o rdfs:label "Hello". }
}
which does the first ?prod :hasProp ?o. then checks whether ?o causes ?o rdfs:label "Hello" to match. Use the form you find easiest to understand.
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.)