Getting time interval - sparql

Apologies if this has been asked before but it seems an obvious question for which I can't seem to get a working solution. I've loaded some data into Fuseki which contains statements comprising xsd:date information. I have written a query to extract these dates and I would like to find the duration (in days) between two specific date. A cut down query is shown below.
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX abc: <http://www.acme.com/ABC/1.0/abc-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?entry
(date1 - date2) AS ?interval)
WHERE
{
# Not the real query but you get the idea
?entry a abc:thing ;
abc:abcDateType1 ?date1 ;
abc:abcDateType2 ?date2 .
}
?interval is calculated correctly and seems to be in the form of an xsd:duration data type, my question is how do I extract the number of days it contains? Alternatively is there a better (standard) way of doing this.
Thank you for reading.

You will need to work with the lexical for of the XSD duration. It is likely to be for the form "PD...."
The answer should be call fn:days-from-duration, or a keyword for that function, but that isn't in the standard distribution at the moment.

One way would be to add unix-style timestamps related to a date, abstractly:
?blankNode eg:hasDate ?date
?blankNode eg:hasEpoch ?epoch
Then you can easily subtract the timestamp for one day from the other, and divide by 86400 to give the answer in day, e.g.:
SELECT ?entry
((?time1 - ?time2)/86400) AS ?interval)
WHERE
{
# Not the real query but you get the idea
?entry a abc:thing ;
abc:abcDateType1 ?date1 ;
abc:abcDateType2 ?date2 .
?blankNode1 hasDate ?date1 .
?blankNode1 hasTime ?time1 .
?blankNode2 hasDate ?date1 .
?blankNode2 hasTime ?time1 .
}

Related

How to use SPARQL to query local ttl file?

I'm learning how to query ttl file that I retrieve from Wikipedia.
However, I stuck on getting the correct query to show the result that I seek for an answer.
Here is the example ttl file that I used.
# File name : WikipediaGraph.ttl
#prefix ns1: <http://www.example.com/> .
<http://en.wikipedia.org/wiki/Abilene,_Texas> ns1:2010population "117063" ;
ns1:2019population "123420" ;
ns1:areaSqKm "276.4" ;
ns1:areaSqMile "106.7" ;
ns1:popChange "5.43" ;
ns1:popPerSqKm "442" ;
ns1:popPerSqMile "1146" ;
ns1:state <http://en.wikipedia.org/wiki/Texas> .
The sample question that I want to get an answer to listed below.
Which state(s) has the most cities in the list? *
Which state(s) has the most population in cities in the list? *
Which state(s) has seen its cities in the list grow the most? *
Therefore, I stuck from the beginning as I can't get the result from the simple query.
import rdflib
from rdflib import Graph, URIRef, Literal, Namespace, RDF
g=rdflib.Graph()
g.parse("WikipediaGraph.ttl", format='turtle')
results = g.query("""
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX ns1: <http://www.example.com/>
SELECT ?v
WHERE {
?v rdf:type ns1:state .
}
ORDER BY ?NAME
""")
print('Results!')
for row in results:
print(row)
Could you please advise how I should write to query the above question?

How to calculate distance between two points using geosparql

I'm trying to calculate the distance between two points using geosparql. I have objects like the following image (same properties, different values):
And I'm executing that query in sparql:
PREFIX geos: <http://www.opengis.net/ont/geosparql#>
PREFIX geosf: <http://www.opengis.net/def/function/geosparql/>
PREFIX : <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#>
SELECT ?distance
WHERE {
?wifipoint1 :hasGeometry ?geo1 .
?geo1 geos:asWKT ?wpoint1 .
FILTER sameterm(?wifipoint1, <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#NYWifiFree103>)
?wifipoint2 :hasGeometry ?geo2 .
?geo2 geos:asWKT ?wpoint2 .
FILTER sameterm(?wifipoint2, <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#NYWifiFree105>) .
?distance geosf:distance(?wpoint1 ?wpoint2 <http://qudt.org/vocab/unit#Kilometer>)
}
Without adding the distance, I'm able to get the following result:
But at the moment I add the distance I get empty rows. Any idea?
Notes:
I need to calculate the distance between two wifipoints (NYWifiFree103 and NYWifiFree105) which have each one a point.
I'm executing that queries in stardog.
** EDIT **
I simplified the query:
PREFIX geos: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX : <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#>
SELECT (geof:distance(?wpoint1, ?wpoint2, <http://qudt.org/vocab/unit#Kilometer>) as ?distance)
WHERE {
?wifipoint1 :hasGeometry ?geo1 .
?geo1 geos:asWKT ?wpoint1 .
FILTER sameterm(?wifipoint1, <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#NYWifiFree103>) .
?wifipoint2 :hasGeometry ?geo2 .
?geo2 geos:asWKT ?wpoint2 .
FILTER sameterm(?wifipoint2, <http://www.semanticweb.org/frubi/ontologies/2017/10/puntsWIFI#NYWifiFree105>)
}
When I set in geof:distance two harcoded wktLiteral returns me correct distance, but using Points does not return nothing.
The geof:distance function accepts Geometries as its first two parameters. So with your simplified query, using geof:distance(?geo1, ?geo2, unit:Kilometer) should give you the result you desire. The Stardog Blog has a geospatial primer post that you may find useful.
AKSW is correct, you should use the built in geof:distance function for the calculation.
I have the same problem with GraphDB. instead of distance it returns 2 fields empty and I have already enabled geosparql
Here is my code:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://www.semanticweb.org/evangelos/ontologies/2019/2/untitled-ontology-2#>
prefix geo: <http://www.opengis.net/ont/geosparql#>
prefix geof: <http://www.opengis.net/def/function/geosparql/>
prefix unit: <http://qudt.org/vocab/unit#>
prefix sf: <http://www.opengis.net/ont/sf#>
prefix test24: <http://www.semanticweb.org/evangelos/ontologies/2019/2/untitled-ontology-2#>
prefix omgeo: <http://www.ontotext.com/owlim/geo#>
SELECT (geof:distance(?point, ?point2, <http://qudt.org/vocab/unit#Kilometer>) as ?distance)
WHERE
{
:MouseioMetaksisSoufliou :hasGPSCoordinates ?geom2.
?geom2 geo:asWKT ?point.
?geom3 geo:asWKT ?point2.
FILTER (?geom2 != ?geom3)
}

SPARQL query returns multiple birth dates for same person

I am learning SPARQL and dbpedia by working through the queries in https://www.joe0.com/2014/09/22/how-to-use-sparql-to-query-dbpedia-and-freebase/ . I am testing a query to return John Lennon's date of birth and I am running my queries in http://dbpedia.org/sparql . The query is:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?x0 ?x1 WHERE {
?x0 rdf:type foaf:Person.
?x0 rdfs:label "John Lennon"#en.
?x0 dbpedia-owl:birthDate ?x1.
}
It returns two rows containing the same date (9 Oct 1940). My question is: why does the query return two rows even though it uses DISTINCT? Prior to asking this question I checked the following:
Why does my SPARQL query duplicate results?
Duplicate rows when making SPARQL queries
but I don't think they explain the duplicate dates.
Edit: I converted the results to text and pasted them below
-------------------------------------- -----------------------------------------------------
x0 x1
--------------------------------------- -----------------------------------------------------
http://dbpedia.org/resource/John_Lennon 1940-10-09
http://dbpedia.org/resource/John_Lennon "1940-10-9"^^<http://www.w3.org/2001/XMLSchema#date>
As stated it seems dbpedia actually has two dates, 1940-10-09 (valid) and 1940-10-9 (invalid). The answer is to add a FILTER that converts the date to a string and only allows dates conforming to YYYY-MM-DD. Anyway it works!
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
SELECT DISTINCT ?x0 ?x1 STR(?x1) WHERE {
?x0 rdf:type foaf:Person.
?x0 rdfs:label "John Lennon"#en.
?x0 dbpedia-owl:birthDate ?x1.
FILTER (REGEX(STR(?x1),"[0-9]{4}-[0-9]{2}-[0-9]{2}")).
}
Well, it is not your fault! Simply the resource has both of these triples as you can see here. There are duplicates in the data.
I ran your query on the DBpedia endpoint and asked for the results in an RDF-based format (Turtle), and found that the lexical forms of the date literals are actually different:
"1940-10-09"^^xsd:date
"1940-10-9"^^xsd:date
The second isn't actually a legal xsd:date. The first is, which is probably why the SPARQL endpoint prints it in "pretty" fashion in the HTML table (as just 1940-10-09).
The result is a slowdown on queries because each access to an invalid date trig an exception (for example, with a query from fuseki) or the filter do the job to eliminate the wrong date, but it's costly

Querying for date range in SPARQL

I have some data in a semantic database that looks like the following, where the first column is the ID of an object, and the second column is the last modified date, as xsd:dateTime's.
?s ?last_mod_date
http://company.com/custom.xml#obj1, 2016-08-30T08:44:49.000-04:00
http://company.com/custom.xml#obj2, 2016-08-30T17:24:21.000-04:00
http://company.com/custom.xml#obj3, 2016-08-30T09:03:57.000-04:00
http://company.com/custom.xml#obj4, 2016-07-27T03:26:44.000-04:00
http://company.com/custom.xml#obj5, 2016-08-11T03:23:53.000-04:00
http://company.com/custom.xml#obj6, 2016-07-19T03:05:03.000-04:00
I'm trying to filter this list of objects down to one item by date; my query input is unfortunately only precise to the minute, so I'm trying to use a date range to find the object, like this:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix cust: <http://company.com/custom.xml#>
SELECT ?s ?date WHERE
{
?s cust:last_mod_date ?date.
BIND("2016-08-30T09:03:00.000-0400"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?minDate).
BIND("2016-08-30T09:04:00.000-0400"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?maxDate).
FILTER(?date > ?minDate && ?date < ?maxDate)
}
The above query should find obj3, but instead it finds nothing. This is with a Sesame semantic database. Any ideas why this would be?
Your datetimes in the SPARQL query are malformed:
BIND("2016-08-30T09:03:00.000-0400"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?minDate).
BIND("2016-08-30T09:04:00.000-0400"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?maxDate).
Should be
BIND("2016-08-30T09:03:00.000-04:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?minDate).
BIND("2016-08-30T09:04:00.000-04:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> as ?maxDate).
The timezone modifier is the first BIND statements are missing a colon.

SPARQL date range

I'm trying to obtain all records between certain dates. The date field has appears in this format: 2012-01-31. I think it is of type: <http://www.w3.org/2001/XMLSchema#date>
How would I modify the query below to extract records with date greater than 2012-01-31 please?
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX lrppi: <http://landregistry.data.gov.uk/def/ppi/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX lrcommon: <http://landregistry.data.gov.uk/def/common/>
SELECT ?county ?postcode ?amount ?date
WHERE
{
?transx lrppi:pricePaid ?amount .
?transx lrppi:transactionDate ?date .
?transx lrppi:propertyAddress ?addr.
?addr lrcommon:postcode "PL6 8RU"^^xsd:string .
?addr lrcommon:postcode ?postcode .
# Cant get this line to work
# ?date lrppi:transactionDate ?date . FILTER ( ?date >= "1327968000"^^xsd:date )
OPTIONAL {?addr lrcommon:county ?county .}
}
ORDER BY ?postcode
If you want to play with this, you can enter your query here:
http://landregistry.data.gov.uk/landregistry/sparql/sparql.html
This is what the FILTER clause is designed for.
The Expressions and Testing Values section of the SPARQL specification covers this in detail, pretty much the first example in that section covers filtering on dates.
Edit
If you are new to SPARQL then I would recommend you read a good SPARQL tutorial like SPARQL by Example which is written by one of the specification authors. This will walk you through various parts of SPARQL and should help you get your head around the RDF data model and query language better.
In terms of dates they are represented using XML schema datatypes, for example expressing today as a date would be the following:
"2013-03-22"^^xsd:date
The linked specification covers the lexical form of various datatypes.
So for your example it would be the following:
FILTER ( ?date >= "2012-01-31"^^xsd:date )
If you are starting from a UNIX timestamp and trying to get to an xsd:date see Generating an xsd:dateTime in shell script which may provide a useful starting point.