Remove duplicates in SPARQL - sparql

Hi I have two csv data sources. The csv contains name of employees.
csv1 with heading: Name
Contents: Jack, Tom, Andy, Jim, Stella.
csv2 with heading: EmployeeName
Contents: Bella, Stefan, Jim, Cathy, Jack
?ABCInstance a ABC:TeamInstance ;
ABC:Name ?Name .
?CDEInstance a CDE:DataInstance ;
CDE:employeeName ?employeeName .
I want to combine values in both the variable and avoid duplicates.
What FILTER or AND or any other statements do I use?

I've had to make some assumptions about how the data in the .csv is represented in triples. If I understand correctly, something like this could work:
PREFIX ABC: <XXXXX>
PREFIX CDE: <XXXXX>
SELECT DISTINCT ?name WHERE
{
VALUES ?entity { ABC:TeamInstance, CDE:DataInstance } .
VALUES ?hasname { ABC:Name, CDE:employeeName }
?iri a ?entity .
?iri ?hasname ?name .
}

Related

SPARQL count item in an intersection

Given the following triples
#prefix ex: <http://example.org/> .
#base <http://example.com/> .
<person1> ex:has_interpretation <interpretation1> .
<interpretation1> ex:refers_to <objectA> ;
ex:resultIn <X> .
<person2> ex:has_interpretation <interpretation2> .
<interpretation2> ex:refers_to <objectA> ;
ex:resultIn <Y> .
<person2> ex:has_interpretation <interpretation3> .
<interpretation3> ex:refers_to <objectB> ;
ex:resultIn <Z> .
<person3> ex:has_interpretation <interpretation4> .
<interpretation3> ex:refers_to <objectA> ;
ex:resultIn <ZZ> .
I am trying to use SPARQL to:
count only the number of object referred to by an interpretation by both person1 and person2 (intersection)
count the number of distinct interpretations over the object
count the number of object not referred to by an interpretation by both person1 and person2
having the above count together with a list of objects referred to by an interpretation and the people who create the interpretation.
I am having trouble specifically with 1 (and consequently, 3), as I cannot find a way to count the intersection of the interpreted objects.
My current SPARQL query which does not obtain what I want:
PREFIX ex: <http://example.org/>
SELECT ?person (COUNT(distinct ?object) as ?c_object) (group_concat(distinct ?interpretation;separator="; ") as ?interpretations)
WHERE {
?person ex:has_interpretation ?interpretation .
?interpretation
ex:refers_to ?object ;
ex:resultIn ?result .
FILTER (?person = <http://example.com/person1> || ?person = <http://example.com/person2> )
}
GROUP BY ?person ?object
What instead I would like is just:
object_uri
number_object
interpretations
person_involved
<objectA>
1
<interpretation1>,<interpretation2>
<person1>,<person2>
Any ideas?
count only the number of object referred to by an interpretation by both person1 and person2 (intersection)
PREFIX ex: <http://example.org/>
SELECT DISTINCT ?obj
WHERE {
<http://example.com/person1> ex:has_interpretation/ex:refers_to ?obj .
<http://example.com/person2> ex:has_interpretation/ex:refers_to ?obj .
}
Here the query matches only those objects (?obj) which have ex:has_interpretation/ex:refers_to paths to them from both <person1> and <person2>.
count the number of distinct interpretations over the object
Just use the COUNT() function as the paths used in the answer for 1. above are distinct (different):
PREFIX ex: <http://example.org/>
SELECT DISTINCT ?obj
WHERE {
<http://example.com/person1> ex:has_interpretation/ex:refers_to ?obj .
<http://example.com/person2> ex:has_interpretation/ex:refers_to ?obj .
}
count the number of object not referred to by an interpretation by both person1 and person2
You might be able to find a fancy way to query for this but I would just count distinct objects:
PREFIX ex: <http://example.org/>
SELECT DISTINCT ?obj
WHERE {
?x ex:refers_to ?obj .
}
...and then subtract the results from 1. above. This is easy to understand and you've already got the results from 1. to work with.

DBpedia SPARQL to eliminate unwanted data

PREFIX category: <http://dbpedia.org/resource/Category:>
SELECT DISTINCT ?attractions
?location
WHERE
{ ?attractions dcterms:subject ?places
. ?places skos:broader ?border
. ?attractions dbpprop:location|dbpedia-owl:locatedInArea|dbpprop:locale ?location
. FILTER( ?border = category:Visitor_attractions_in_Delhi )
}
I have above query giving result of attraction location of Delhi. I need to make it generic for all places, and secondly I want to filter out unwanted data. I want only attraction places, e.g., I didn't want List of Monuments and SelectCityWalk like data in my output.

DBPedia SPARQL OPTIONAL

I am running this simple query on http://dbpedia.org/sparql
PREFIX p: <http://dbpedia.org/property/>
SELECT * WHERE {
?person dcterms:subject category:British_journalists .
OPTIONAL { ?person p:name ?name } .
OPTIONAL { ?person p:dateOfBirth ?dob } .
}
LIMIT 10
I expect to get the first 10 people from http://dbpedia.org/resource/Category:British_journalists whether they have name and dateOfBirth or not. I am getting the first 10 people who have both properties. For e.g. there are 2 missing people after Andrew Rothstein.
What am I doing wrong?
The problem with your query is that a) LIMIT limits the number of rows returned, not subjects, and b) some people have more than one name.
So, for example, the journalist Daniel Singer (http://dbpedia.org/resource/Daniel_Singer_(journalist)) has at least two names: "Daniel Singer"#en and "Singer, Daniel"#en. That doubles the number of rows with him as a subject.
If you GROUP BY ?person you ensure only one person per row. You then need to SAMPLE names and dobs to pick just one per person.
PREFIX p: <http://dbpedia.org/property/>
SELECT ?person (SAMPLE(?name) as ?aname) (SAMPLE(?dob) as ?adob) WHERE {
?person dcterms:subject category:British_journalists .
OPTIONAL { ?person p:name ?name } .
OPTIONAL { ?person p:dateOfBirth ?dob } .
}
GROUP BY ?person
LIMIT 10
(I'm not sure how well SAMPLE plays with unbound cases, i.e. where there isn't a name)
As per O.R Mapper's comment - removing the limit brings full result set which reveals that OPTIONAL is in fact working.
Thank you.

restricting DISTINCT in SPARQL

I want to get the name, the surname and place of birth from a certain graph. I get results like "John" "Doe" "London" and "John" "Doe" "UK" . Is there a way to restrict and express somehow the DISTINCT in only the 2 (name and surname?) out of 3 (name, surname and birthplace) ?
You haven't shown any example data or queries you've tried which makes this question harder to answer, please include those details in future.
One approach is to use GROUP BY instead of DISTINCT e.g.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?surname (SAMPLE(?loc) AS ?location)
WHERE
{
?person foaf:givenName ?name ;
foaf:familyName ?surname ;
foaf:based_near ?loc .
}
GROUP BY ?name ?surname
This query groups your results together by ?name and ?surname and selects one of the possible locations for each group of results.
The SAMPLE() aggregate used here basically asks the query engine to select one possible value for a non-group key variable from the grouped results.

How to know if a string is a proper name of person or a place name using DBpedia?

I am using SPARQL query on DBpedia into a Prolog project and I have a doubt. I would know if a word is, most probably, a NAME OF A PERSON (something like: John, Mario) or a PLACE (like a city: Rome, London, New York).
I have implement the following two queries, the first gives me the number of persons having a specific name, and the second gives me the number of places having a specific name.
1) Query for a PERSON NAME:
select COUNT(?person) where {
?person a dbpedia-owl:Person .
{ ?person foaf:givenName "John"#en }
UNION
{ ?person foaf:surname "John"#en }
}
For the name John, I obtain the following output: callret-0: 7313, so I think that it has found 7313 instances for the proper name John. Is it right?
2) Query for a PLACE NAME:
select COUNT(?place) where {
?place a dbpedia-owl:Place .
{ ?x rdfs:label "John"#en }
}
The problem is that, as you can see in the previous “place” query, I have inserted John as parameter, which is not a place name but a proper name of persons, but I obtain the following strange result: callret-0: 81900104
The problem is that, in this way, if I compare the output of the previous two queries, it seems that John is a place and not a person name! This is not good for my scope; I have tried with other personal names and it always happens that the place query gives me a bigger output than the name query.
Why? What am I missing? Are there some errors in my queries? How can I solve it to have a correct result?
Actually, when I run the query you provided:
select COUNT(?place) where {
?place a dbpedia-owl:Place .
{ ?x rdfs:label "John"#en }
}
I get the result 93027312, not 81900104, but that does not really matter much. The strange results arise because ?x and ?place don't have to be bound to the same thing, so you are getting all the dbpedia-owl:Places and counting them, but the number of result rows is the number of dbpedia-owl:Place multiplied by the number of things with rdfs:label "John#en":
select COUNT(?place) where { ?place a dbpedia-owl:Place }
=> 646023
select COUNT(?x) where { ?x rdfs:label "John"#en }
=> 144
646023 × 144 = 93027312
If you actually ask for dbpedia-owl:Places that have the rdfs:label "John#en", you'll get no results:
select COUNT(?place) as ?numPlaces where {
?place a dbpedia-owl:Place ;
rdfs:label "John"#en .
}
SPARQL results
Also, you might consider using dbpprop:name instead of rdfs:label. Some results seem like they are more useful that way. For instance, let us find places called "Springfield". If we ask for places with that name we get no results:
select * where {
?place a dbpedia-owl:Place ;
rdfs:label "Springfield"#en .
}
SPARQL results
However, if we modify the query and use dbpprop:name, we get 17. Some of these are duplicates though, so you might have to do something else to remove duplicates. The point, though, is that dbpprop:name got some results, and rdfs:label didn't.
select * where {
?place a dbpedia-owl:Place ;
dbpprop:name "Springfield"#en .
}
SPARQL results
You can even use dbpprop:name in working with the names of persons, although it's not as useful, because the dbpprop:name value for most persons is their entire name. To find persons with the given name John using dbpprop:name requires a query like:
select * where {
?place a dbpedia-owl:Person ;
dbpprop:name ?name .
FILTER( STRSTARTS( str( ?name ), "John" ) )
}
(or you could use CONTAINS instead of STRSTARTS), but this becomes much more expensive, because it has to select all persons and their names, and then filter through that set. Being able to select persons based on a specific name (e.g., with foaf:givenName) is much more efficient.