SPARQL select statements where value might not exists - sparql

I am trying to select data from a query but it will only work when all the data exists.
I am new to SPARQL and can't seem to get the optional parts of my query working.
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT ?label ?computingPlatform ?developer ?genre ?publisher ?releaseDate ?series
WHERE {
<http://dbpedia.org/resource/Elden_Ring> rdfs:label ?label .
<http://dbpedia.org/resource/Elden_Ring> dbo:computingPlatform ?computingPlatform .
<http://dbpedia.org/resource/Elden_Ring> dbo:developer ?developer .
<http://dbpedia.org/resource/Elden_Ring> dbo:genre ?genre .
<http://dbpedia.org/resource/Elden_Ring> dbo:publisher ?publisher .
<http://dbpedia.org/resource/Elden_Ring> dbo:releaseDate ?releaseDate .
<http://dbpedia.org/resource/Elden_Ring> dbo:series ?series .
}
So looking at the above if for example "developer" didn't exist on the resource the query would return no results.

PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT ?label ?computingPlatform ?developer ?genre ?publisher ?releaseDate ?series
WHERE {
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> rdfs:label ?label .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:computingPlatform ?computingPlatform .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:developer ?developer .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:genre ?genre .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:publisher ?publisher .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:releaseDate ?releaseDate .}
OPTIONAL {<http://dbpedia.org/resource/Elden_Ring> dbo:series ?series .}
}

Related

(SPARQL) BIND fails with values from nested query

I have been having problems with BIND IF in nested query (SPARQL). BIND fails and returns empty column (?koordColor) if I try to evaluate and bind value from inner query ?pop20 and ?pop14-?pop20 but is successful if I evaluate and bind ?pop14. Does anyone know how to fix this query so that I could evaluate and bind according to ?pop14-?pop20 value successfully?
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX qb: <http://purl.org/linked-data/cube#>
PREFIX lvcsb: <http://127.0.0.1:8080/LOD/>
PREFIX lvcsb-geo: <http://127.0.0.1:8080/LOD/territory/>
prefix opengis: <http://www.opengis.net/ont/geosparql#>
prefix lvl: <http://127.0.0.1:8080/LOD/statLevel/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?label ?koordColor ?koord ?pop20 ?pop14
WHERE {
?obs a qb:Observation.
?obs lvcsb:refPeriod 2014.
?obs lvcsb:refArea ?area.
?area lvcsb:version ?ver.
?ver rdfs:label ?label.
?ver opengis:Geometry ?geo.
?geo opengis:asWKT ?koord.
?obs lvcsb:population ?pop14.
BIND(IF(?pop14-?pop20 > 1000, "green", "blue") AS ?koordColor)
{SELECT ?label ?pop20 WHERE {
?obs a qb:Observation.
?obs lvcsb:refPeriod 2020.
?obs lvcsb:refArea ?area.
?area lvcsb:version ?ver.
?ver rdfs:label ?label.
?obs lvcsb:population ?pop20.
{SELECT distinct ?label where{
?obs a qb:Observation.
?obs lvcsb:refArea ?area.
?area lvcsb:version ?ver.
?ver rdfs:label ?label .
?ver lvcsb:statLevel ?level .
filter(?level = lvl:4 )
filter(lang(?label)='lv')}
}}
}}

Sparql query issue with DBpedia retrieving

I'm trying to run this Sparql statement to read data from DBpedia; However, it only return the column names and no row data.
If anybody can let me know what's the issue. I'll be more appreciated
Sparql query below:
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?actor ?movie ?director ?movie_date
WHERE {
?m dc:subject <http://dbpedia.org/resource/Category:American_films> .
?m rdfs:label ?movie .
FILTER(LANG(?movie) = "en")
?m dbp:released ?movie_date .
FILTER(DATATYPE(?movie_date) = xsd:date)
?m dbp:starring ?a .
?a rdfs:label ?actor .
FILTER(LANG(?actor) = "en")
?m dbp:director ?d .
?d rdfs:label ?director .
FILTER(LANG(?director) = "en")
}
The problem is not all the queried triples exist. If at least one of the relations doesnt exist, no result will be given.
So with the OPTIONAL keyword, answers will be given only if they exist and wont block your query if they don't. It simply leaves the missing value empty.
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?actor ?movie ?director ?movie_date
WHERE {
?m dc:subject <http://dbpedia.org/resource/Category:American_films> .
OPTIONAL{
?m rdfs:label ?movie .
FILTER(LANG(?movie) = "en") }
OPTIONAL {
?m dbp:released ?movie_date .
FILTER(DATATYPE(?movie_date) = xsd:date) }
OPTIONAL{
?m dbp:starring ?a .
?a rdfs:label ?actor .
FILTER(LANG(?actor) = "en") }
OPTIONAL{
?m dbp:director ?d .
?d rdfs:label ?director .
FILTER(LANG(?director) = "en") }
}

Duplicated results from Wikidata

I created the following SPARQL query to Wikidata. And the result of this query are records related to states in Germany. But as you can see, results are occurring four times in a row (you can test it here: https://query.wikidata.org/). I supposed that there is a problem with geo coordinates and languages but I can't resolve it anyway. What is wrong with this query and how can I fix it to receive a result without repetition?
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX schema: <http://schema.org/>
PREFIX psv: <http://www.wikidata.org/prop/statement/value/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
PREFIX wikibase: <http://wikiba.se/ontology#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX wd: <http://www.wikidata.org/entity/>
SELECT DISTINCT ?subject ?featureCode ?countryCode ?name ?latitude ?longitude ?description ?iso31662
WHERE
{ ?subject wdt:P31 wd:Q1221156 ;
rdfs:label ?name ;
wdt:P17 ?countryClass .
?countryClass
wdt:P297 ?countryCode .
?subject wdt:P31/(wdt:P279)* ?adminArea .
?adminArea wdt:P2452 "A.ADM1" ;
wdt:P2452 ?featureCode .
?subject wdt:P300 ?iso31662
OPTIONAL
{ ?subject schema:description ?description
FILTER ( lang(?description) = "en" )
?subject p:P625 ?coordinate .
?coordinate psv:P625 ?coordinateNode .
?coordinateNode
wikibase:geoLatitude ?latitude ;
wikibase:geoLongitude ?longitude
}
FILTER ( lang(?name) = "en" )
FILTER EXISTS { ?subject wdt:P300 ?iso31662 }
}
ORDER BY lcase(?name)
OFFSET 0
LIMIT 200
In short, "9.0411111111111"^^xsd:double and "9.0411111111111"^^xsd:decimal are distinct, though they might be equal in some sense.
Check this:
SELECT DISTINCT ?subject ?featureCode ?countryCode ?name ?description ?iso31662
(datatype(?latitude) AS ?lat)
(datatype(?longitude) AS ?long)
and this:
SELECT DISTINCT ?subject ?featureCode ?countryCode ?name ?description ?iso31662
(xsd:decimal(?latitude) AS ?lat)
(xsd:decimal(?longitude) AS ?long)

how can i get list of book from Wikibooks with SPARQL query

how can i get list of book from Wikibooks with SPARQL query fo example :
PREFIX dbo:http://dbpedia.org/ontology/
PREFIX dba:http://dbpedia.org/ontology/
SELECT ?author ?name ?label ?text ?title ?isbn ?publisher ?literaryGenre ?pages WHERE
{?book a dbo:Book.
?book dbo:author ?author.
?book dbo:numberOfPages ?pages.
?book dbp:title ?title.
?book dba:isbn ?isbn.
?book dba:publisher ?publisher.
FILTER regex(?title , "java") .
}
I'm wondering whether you know that Wikibooks is not Wikipedia and DBpedia is based on Wikipedia?!
And then, why do you have two prefixes dbo and dba for the same namespace http://dbpedia.org/ontology/ ? I really suggest to understand what you're doing and what the query does instead of copy and paste from some other sources. SPARQL and RDF tutorials might help, and also the official documentation is useful.
Next issue, you SELECT variables ?name, ?label, ?text and ?literaryGenre which are not bound in a triple pattern in the WHERE part. It's also not clear what you expect to get for ?text. The whole text of the book?! For sure, this won't exist, think about copyrights.
And what would be the difference between ?name and ?title? I don't think that dbp:title is the appropriate property here, see
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT count(*) WHERE {
?book a dbo:Book ;
dbp:title ?title.
}
which returns 19 only.
My suggestion:
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT * WHERE {
?book a dbo:Book .
?book dbo:author ?author .
OPTIONAL { ?book dbo:numberOfPages ?pages }
OPTIONAL { ?book dbo:isbn ?isbn }
OPTIONAL { ?book dbo:publisher ?publisher }
# get the English title
?book rdfs:label ?name.
FILTER(LANGMATCHES(LANG(?name), 'en'))
# get an English description, but not the text
?book rdfs:comment ?text .
FILTER(LANGMATCHES(LANG(?text), 'en'))
# filter for books whose title contains "java"
FILTER regex(str(?name) , "java", "i") .
}
More efficient using the Virtuoso fulltext index predicate bif:contains:
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT * WHERE {
?book a dbo:Book .
?book dbo:author ?author .
OPTIONAL { ?book dbo:numberOfPages ?pages }
OPTIONAL { ?book dbo:isbn ?isbn }
OPTIONAL { ?book dbo:publisher ?publisher }
# get the English title
?book rdfs:label ?name.
FILTER(LANGMATCHES(LANG(?name), 'en'))
# get an English description, but not the text
?book rdfs:comment ?text .
FILTER(LANGMATCHES(LANG(?text), 'en'))
# filter for books whose title contains "java"
?name bif:contains '"java"'
}
As a book might have multiple authors resp. publisher you might get duplicate rows, here GROUP_BY in combination with GROUP_CONCAT is the way to go (grouped by book):
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?book (group_concat(DISTINCT ?author; separator = ", ") as ?authors) (group_concat(DISTINCT ?publisher; separator = ", ") as ?publishers) (sample(?pages) as ?numPages) (sample(?isbn_tmp) as ?isbn) WHERE {
?book a dbo:Book .
?book dbo:author ?author .
OPTIONAL { ?book dbo:numberOfPages ?pages }
OPTIONAL { ?book dbo:isbn ?isbn_tmp }
OPTIONAL { ?book dbo:publisher ?publisher }
# get the English title
?book rdfs:label ?name.
FILTER(LANGMATCHES(LANG(?name), 'en'))
# get an English description, but not the text
?book rdfs:comment ?text .
FILTER(LANGMATCHES(LANG(?text), 'en'))
# filter for books whose title contains "java"
?name bif:contains '"java"'
}
GROUP BY ?book

Federated queries on dbpedia and linkedmdb

I am writing a federated query to get the books based on films in dbpedia and in turn using the film name from dbpedia to retrieve the corresponding imdblink link for the same. I am getting an empty set when I add the service of linkedmdb.
Here is my code
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX movie: <http://data.linkedmdb.org/resource/movie/>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT distinct ?name ?author ?filmname ?imdbID WHERE {
SERVICE <http://dbpedia.org/sparql> {
?book rdf:type dbo:Book .
?book foaf:name ?name .
?book dbp:author ?author .
?author foaf:name ?authname .
?book ^dbo:basedOn ?movie .
?movie a dbo:Film .
?movie foaf:name ?filmname
FILTER (str(?name) IN ("Royal Flash","White Oleander", "Possession: A Romance", "Misery", "Intensity", "The War of The Roses", "Momo", "The Sicilian", "Derailed", "Ragtime"))
}
SERVICE <http://data.linkedmdb.org/sparql> {
?filmname foaf:page ?imdbID .
?filmname dc:title ?title .
FILTER(regex(str(?imdbID), "www.imdb.com" ) )
}
}
I am using the following endpoint http://www.sparql.org/query.html
That does not work because of the ?filename variable
in the first SERVICE clause you get
?movie foaf:name ?filmname, thus, those are string literals
in the second SERVICE clause ?filmname are URIs
It will become easy to see if you run both SPARQL queries separately.
What you would have to do is to match on the title, i.e. change
?filmname dc:title ?title .
to
?filmname dc:title ?filmname .
Note, this might not work because of different types of strings, e.g. with and without language tag etc.
In that case you would have to match on the lexical form again, i.e. use temporary variables ?filmname1 and ?filmname2 and use
FILTER(str(?filmname1) = str(?filmname2))
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX movie: <http://data.linkedmdb.org/resource/movie/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/terms/>
SELECT DISTINCT ?name ?author ?filmname1 ?imdbID
WHERE
{ SERVICE <http://dbpedia.org/sparql>
{ ?book rdf:type dbo:Book ;
foaf:name ?name ;
dbp:author ?author .
?author foaf:name ?authname .
?book ^dbo:basedOn ?movie .
?movie rdf:type dbo:Film ;
foaf:name ?filmname1
FILTER ( str(?name) IN ("Royal Flash", "White Oleander", "Possession: A Romance", "Misery", "Intensity", "The War of The Roses", "Momo", "The Sicilian", "Derailed", "Ragtime") )
}
SERVICE <http://data.linkedmdb.org/sparql>
{ ?filmname foaf:page ?imdbID ;
dc:title ?filmname2
FILTER regex(str(?imdbID), "www.imdb.com")
}
FILTER ( str(?filmname1) = str(?filmname2) )
}