Nested SPARQL Query - sparql

I have the following structure an Object and each Object has multiple Children as Changelog to the Parent Object and each Change Log has an Author.
Now each Changelog has status and Timestamp I would now like to write a SPARQL query where I need to get the list of Objects which has me as the author and of particular status say "to be approved" and it has to be the latest changelog.
This query is what I have tried so far :
I try to get first the changelog then the object related to it after that get all the other changelog in it and compare the latest changelog by timestamp and filter it if it is greater.
select ?Object WHERE{ ?author myPrefix:userId "myuserid".
?changelog myPrefix:hasApprover ?author .
?changelog myPrefix:timestamp ?dv
FILTER( ?dv >= ?latestdate )
{
SELECT (max(?dv1) AS ?latestdate) WHERE {
?Object myPrefix:hasChangeLog ?changelog .
?Object myPrefix:hasChangeLog ?changelog1 .
?changelog1 myPrefix:timestamp ?dv1 .
}
}
?changelog myPrefix:status "To be approved" .
?Object myPrefix:hasChangeLog ?changelog .}
What I am doing wrong here is that it compares it to all the Objects changelog and not Objectwise comparison how can I achieve that?

As per the suggestion from UninformedUser:
select ?Object WHERE{ ?author myPrefix:userId "myuserid".
?changelog myPrefix:hasApprover ?author .
?changelog myPrefix:timestamp ?dv
FILTER( ?dv >= ?latestdate )
{
SELECT (max(?dv1) AS ?latestdate) WHERE {
?Object myPrefix:hasChangeLog ?changelog1 .
?changelog1 myPrefix:timestamp ?dv1 .
}group by ?Object
}
?changelog myPrefix:status "To be approved" .
?Object myPrefix:hasChangeLog ?changelog .}

Related

How to extract RDF triples with specific predicates using sparql

I uploaded a set of RDF triples onto a local Virtuoso endpoint.
Of all these triples, I would like to extract only those whose subjects have at least the predicates http://www.w3.org/2000/01/rdf-schema#label and http://www.w3.org/2000/01/rdf-schema#comment.
For example, from these triples:
<http://dbpedia.org/resource/AccessibleComputing> <http://www.w3.org/2000/01/rdf-schema#label> "AccessibleComputing"#en .
<http://dbpedia.org/resource/AfghanistanGeography> <http://www.w3.org/2000/01/rdf-schema#label> "AfghanistanGeography"#en .
<http://dbpedia.org/resource/AfghanistanGeography> <http://www.w3.org/2000/01/rdf-schema#comment> " ... " .
<http://dbpedia.org/resource/Austroasiatic_languages> <http://www.w3.org/2000/01/rdf-schema#comment> " ... " .
<http://dbpedia.org/resource/AccessibleComputing> <http://dbpedia.org/ontology/wikiPageWikiLink> <http://dbpedia.org/resource/Computer_accessibility> .
<http://dbpedia.org/resource/AfghanistanGeography> <http://dbpedia.org/ontology/wikiPageWikiLink> <http://dbpedia.org/resource/Afghanistan_Geography> .
I would like to get:
<http://dbpedia.org/resource/AfghanistanGeography> <http://www.w3.org/2000/01/rdf-schema#label> "AfghanistanGeography"#en .
<http://dbpedia.org/resource/AfghanistanGeography> <http://www.w3.org/2000/01/rdf-schema#comment> " ... " .
<http://dbpedia.org/resource/AfghanistanGeography> <http://dbpedia.org/ontology/wikiPageWikiLink> <http://dbpedia.org/resource/Afghanistan_Geography> .
Is it possible to do this with one (or more) SPARQL query?
Thank you for helping
This can be done with a CONSTRUCT WHERE query:
CONSTRUCT WHERE {
?s rdfs:label ?label.
?s rdfs:comment ?comment.
?s ?p ?o
}
This is a simplified form of CONSTRUCT that can be used when the CONSTRUCT {} part and the WHERE {} part are identical.
One way is to use DESCRIBE, e.g.:
DESCRIBE ?s
WHERE {
?s rdfs:label ?label .
?s rdfs:comment ?comment .
}
or alternatively with CONSTRUCT :
CONSTRUCT { ?subject ?predicate ?object}
WHERE {
?subject ?predicate ?object .
FILTER EXISTS {
?subject rdfs:label ?label .
?subject rdfs:comment ?comment .
}
}

Aggregate properties

I'm developing my own Fuseki endpoint from some DBpedia data.
I'm in doubt on how to aggregate properties related to a single resource.
SELECT ?name ?website ?abstract ?genre ?image
WHERE{
VALUES ?s {<http://dbpedia.org/resource/Attack_Attack!>}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image } .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}
SPARQL endpoint: http://dbpedia.org/sparql/
This query returns 2 matching results. They are different just for the dbo:genre value. There is a way I can query the knowledge base and retrieving a single result with a list of genres?
#chrisis's query works well on the DBpedia SPARQL Endpoint, which is based on Virtuoso.
However, if you are using Jena Fuseki, you should use more conformant syntax:
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbp: <http://dbpedia.org/property/>
SELECT
?name
(SAMPLE(?website) AS ?sample_website)
(SAMPLE(?abstract) AS ?sample_abstract)
(SAMPLE(?image) AS ?sample_image)
(GROUP_CONCAT(?genre; separator=', ') AS ?genres)
WHERE {
VALUES (?s) {(<http://dbpedia.org/resource/Attack_Attack!>)}
?s foaf:name ?name ;
dbo:abstract ?abstract .
OPTIONAL { ?s dbo:genre ?genre } .
OPTIONAL { ?s dbp:website ?website } .
OPTIONAL { ?s dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
} GROUP BY ?name
The differences from the #chrisis's query are:
Since GROUP_CONCAT is an aggregation function, it might be used with GROUP BY only;
Since GROUP BY is used, all non-grouping variables should be aggregated (e.g. via SAMPLE);
GROUP_CONCAT syntax is slightly different.
In Fuseki, these AS in the projection are in fact superfluous: see this question and comments.
Yes, the GROUP_CONCAT() function is what you want.
SELECT ?name ?website ?abstract (GROUP_CONCAT(?genre,',') AS ?genres) ?image
WHERE{
<http://dbpedia.org/resource/Attack_Attack!> a dbo:Band ;
foaf:name ?name;
dbo:abstract ?abstract .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:genre ?genre } .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbp:website ?website} .
OPTIONAL{ <http://dbpedia.org/resource/Attack_Attack!> dbo:image ?image} .
FILTER LANGMATCHES(LANG(?abstract ), "en")
}

After (GROUP_CONCAT can't get single results

I am not very used to SPARQL, but I managed to write my own query for books and their genres, authors and their dates of birth and death at https://query.wikidata.org
SELECT
?title ?titleLabel
(GROUP_CONCAT(DISTINCT(?authorLabel); separator="//") as ?authors)
(GROUP_CONCAT(DISTINCT(?dateborn); separator="//") as ?date_born)
(GROUP_CONCAT(DISTINCT(?datedeath); separator="//") as ?date_death)
(GROUP_CONCAT(DISTINCT(?datepub); separator="//") as ?date_pub)
(GROUP_CONCAT(DISTINCT(?genre_titleLabel); separator="//") as ?genre_title)
WHERE
{
?title wdt:P31 wd:Q571 .
?title wdt:P50 ?author .
?title wdt:P577 ?date_pub .
?author wdt:P569 ?date_born .
?author wdt:P570 ?date_death .
?title wdt:P136 ?genre_title .
BIND(CONCAT(STR(DAY(?date_pub)),"-",STR(MONTH(?date_pub)),"-",STR(YEAR(?date_pub))) AS ?datepub )
BIND(CONCAT(STR(DAY(?date_born)),"-",STR(MONTH(?date_born)),"-",STR(YEAR(?date_born))) AS ?dateborn )
BIND(CONCAT(STR(DAY(?date_death)),"-",STR(MONTH(?date_death)),"-",STR(YEAR(?date_death))) AS ?datedeath )
FILTER (?date_born > "1900-01-01T00:00:00Z"^^xsd:dateTime) .
FILTER (?date_born < "1905-12-31T23:59:59Z"^^xsd:dateTime)
SERVICE wikibase:label {
bd:serviceParam wikibase:language "en" .
?title rdfs:label ?titleLabel .
?author rdfs:label ?authorLabel .
?date_pub rdfs:label ?date_pubLabel .
?date_born rdfs:label ?date_bornLabel .
?date_death rdfs:label ?date_deathLabel .
?genre_title rdfs:label ?genre_titleLabel .
}
}
GROUP BY ?title ?titleLabel
It works and I get all the genres in the same field. The only way I could get this was with
(GROUP_CONCAT(DISTINCT(
for genres and dates. But If you loook in the results there are records with more than one date. And I want to get only the first date, and not all the stored dates in the database for this record, but I can't.
For example, If I ask for
?dateborn
instead of
(GROUP_CONCAT(DISTINCT(?dateborn); separator="//") as ?date_born)
I get an error. Do you know where is my mistake?
Greets
N.

Get all settlements coordinates in Israel from DBpedia

For my application I want to get the names and the geographic coordinates of most of settlements in Israel (Tel Aviv, Haife etc.).
My idea is to get it from DBpedia (querying the English pages is enough for me).
I tried this query:
SELECT distinct ?subject AS ?mainSubject ?o1 AS ?name ?o2 AS ?point ?o3 AS ?country
WHERE {?subject ?property <http://dbpedia.org/ontology/PopulatedPlace>.
?subject <http://xmlns.com/foaf/0.1/name> ?o1.
?subject <http://www.georss.org/georss/point> ?o2.
?subject <http://dbpedia.org/ontology/country> ?o3.
filter (contains(str(?o3),"Israel")) }
but I get only a few results.
For example I don't get :
https://en.wikipedia.org/wiki/Afula
https://en.wikipedia.org/wiki/Nahariya
Any ideas for better query?
Thanks.
You cannot get the results you want because they do not have georss information that you request. You can do it by OPTIONAL clause.
SELECT distinct ?subject AS ?mainSubject ?o1 AS ?name ?o2 AS ?point ?o3 AS ?country WHERE {
?subject ?property <http://dbpedia.org/ontology/PopulatedPlace>.
?subject <http://xmlns.com/foaf/0.1/name> ?o1.
OPTIONAL{?subject <http://www.georss.org/georss/point> ?o2.}
?subject <http://dbpedia.org/ontology/country> ?o3.
filter (contains(str(?o3),"Israel")) }
On the other hand, instead of FILTER you can directly put the resource of Israel:
SELECT distinct ?subject AS ?mainSubject ?o1 AS ?name ?o2 AS ?point WHERE {
?subject ?property <http://dbpedia.org/ontology/PopulatedPlace>.
?subject <http://xmlns.com/foaf/0.1/name ?o1.
OPTIONAL{?subject <http://www.georss.org/georss/point> ?o2.}
?subject <http://dbpedia.org/ontology/country> <http://dbpedia.org/resource/Israel>. }

SPARQL Query to get Movie detail

To get movie detail from linkedmdb, I used sparql query :
PREFIX mdb: <http://data.linkedmdb.org/resource/movie/film>
SELECT DISTINCT ?Title ?Genre ?Actor ?Country ?Director ?Year WHERE {
?film mdb:id ?uri .
?film dc:title ?Title .
?film movie:genre ?filmgenre.
?filmgenre movie:film_genre_name ?Genre .
?film movie:actor ?cast .
?cast movie:actor_name ?Actor .
?film movie:country ?Ctr .
?Ctr movie:country_name ?Country .
?film dc:date ?Year .
?film movie:director ?Drc .
?Drc movie:director_name ?Director
FILTER regex(?Title, "Kingdom of Heaven")
}
But SPARQL results shown Title same as counted Actor . How to combine the query so that Title is not repeated?
I've try using GROUP_CONCAT but not working in LinkedMDB Endpoint?
Could someone guide me?