SPARQL subquery wtih xsd:dateTime - sparql

I've made one query which returns the date of the Hiroshima bombing.
SELECT ?date
WHERE {
history:the_bombing_of_hiroshima history:hasStartDate ?date .
}
Result: 1945-08-06T:00:00:00
And another query which returns all of the administration that ruled the Soviet Union.
SELECT ?administration
WHERE {
?administration history:rulesCountry "The Soviet Union"^^xsd:string .
}
Now, I'm wondering. An administration in our ontology has a "startDate" and "endDate" data property. Both containing xsd:dateTime values. I want to pass the date, received from the first query into the second query so that we can get the administration that ruled the Soviet Union during the bombing of Hiroshima.
I've tried to read some SPARQL subquery examples but none of them concern dateTime filtering (check to see if a date falls between two others) and many of them are a bit confusing to me.
I suspect the query must be something like
SELECT ?administration
WHERE {
?administration history:rulesCountry "The Soviet Union"^^xsd:string .
?administration history:hasStartDate > [RESULT FROM QUERY1 HERE] && history:hasEndDate < [RESULT FROM QUERY1 HERE]
}
I'd be very grateful for any answers or pointers towards resources and tutorials I can read to get this query to work.

Related

SPARQL SubQuery in Filter

SELECT ?Name FROM <http://.../biblio.rdf>
WHERE { ?Aut name ?Name . ?Pub author ?Aut . ?Pub conf ?Conf
FILTER (?Conf IN ( SELECT ?ConfX FROM <http://.../biblio.rdf>
WHERE { ?ConfX series "ISWC" }))}
I have taken the query from http://www.renzoangles.net/files/amw2011.pdf.
Getting the malformed query syntax error when I tried the above format in AWS Neptune.
Please help me fix the above query.
If you want to test that a triple is in the data, which seems to be the intention of the exampel of "FILTER IN SELECT " here, yuo can use FILTER EXISTS
FILTER EXISTS { ?Conf series "ISWC" }

SPARQL Restrict Number of Results for Specific Variable

Suppose I want to look for some first degree neighbors of Berlin. I ask the following query:
select ?s ?p where {
?s ?p dbr:Berlin.
}
Is it possible to put a restriction on the return result, such that there are at most 5 results for each unique value of ?p?
My attempts with subqueries all time out...
But, as potentially useful if not exactly perfect solution, maybe GROUP_CONCAT, MAX/MIN or SAMPLE are of use?
SELECT
?writer (GROUP_CONCAT(?namestring; SEPARATOR = " ") AS ?namestrings)
(MIN(?namestring) AS ?min_name)
(MAX(?namestring) AS ?max_name)
(SAMPLE(?namestring) AS ?random_name)
(SAMPLE(?namestring) AS ?another_random_name_that_may_unfortunately_be_the_same_again)
WHERE {
?writer wdt:P31 wd:Q5;
wdt:P166 wd:Q37922;
wdt:P735 ?firstname.
?firstname wdt:P1705 ?namestring.
}
GROUP BY ?writer
HAVING ((COUNT(?writer)) > 2 )
LIMIT 20
See it live here.
And, as you can see, SAMPLE is apparently evaluated only once, so using it repeatedly does not get you closer to five (different) samples.
(You can leave out the HAVING for your use. I only included it to restrict it to useful examples))

Aggregate functions in Sparql query with empty records

I've been trying to run a sparql query against https://landregistry.data.gov.uk/app/qonsole# to yield some sold properties result.
The query is the following:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
SELECT sum(?ukhpi_salesVolume)
WHERE
{ { SELECT ?ukhpi_refMonth ?item
WHERE
{ ?item ukhpi:refRegion <http://landregistry.data.gov.uk/id/region/haringey> ;
ukhpi:refMonth ?ukhpi_refMonth
FILTER ( ?ukhpi_refMonth >= "2019-03"^^xsd:gYearMonth )
FILTER ( ?ukhpi_refMonth < "2020-03"^^xsd:gYearMonth )
}
}
OPTIONAL
{ ?item ukhpi:salesVolume ?ukhpi_salesVolume }
}
The problem is, the result from this is empty. However, if i run the same query without the SUM on the 4th line, i can see there are 11 integer records.
My thoughts are that there is a 12th, empty record which causes all the issues in the SUM operation, but sparql is not my storngest side so i'm not sure how to filter this (and remove any empty records) if that's really the problem.
I've also noticed that most of the aggregate functions do not work as well(min, max, avg). *Count does, and returns 11
I actually solved this myself, all that was needed was a coalesce which apparently existed in sparql too.
So:
SELECT sum(COALESCE(?ukhpi_salesVolume, 0))
instead of just
SELECT sum(?ukhpi_salesVolume)

Query for age in sparql

I am writing a query that calculates the age of someone knowing their birthdate and deathdate. I want to ask for a certain artist (in this case Michael Jackson). The problem is that I can't reuse the birthdate and deathdate in the following query:
select ?artist ?age
where {
dbr:Michael_Jackson dbo:birthDate ?birthdate .
dbr:Michael_Jackson dbo:deathDate ?deathdate .
bind( year(?deathdate) - year(?birthdate) - if(month(?deathdate)<month(?birthdate) || (month(?deathdate)=month(?birthdate) && day(?deathdate<day(?birthdate)),1,0) as ?age)
}
Anyone knows how to solve this problem?
I edited the query a bit to get the values you're calculating against --
birthdate deathdate
"1958-8-29"^^<http://www.w3.org/2001/XMLSchema#date> "2009-6-25"^^<http://www.w3.org/2001/XMLSchema#date>
The error you're hitting is because these are not valid xsd:date literals -- which require 2 digits for the month.
This data issue has been fixed on Wikipedia and so on DBpedia-Live, and your query works there, as you can see. There are other issues with DBpedia-Live data (such as multiple versions of the abstract being shown, when you really only want to see the latest), but perhaps this solves your immediate need.

Remove time from datetime in spaqrl

I am writing a query in SPARQL and I want to compare the date value without the time. Currently, I am getting a datetime value such as 2014-08-14T13:00:00Z. However, I want to do a filter on the date such as
FILTER (?date = "2014-08-15"^^xsd:dateTime)
I am new to SPARQL, so I need some help. Thanks.
EDITED
Thanks for the response guys. My apologies for the xsd:dateTime
FILTER (?date = "2014-08-15"^^xsd:date)
I have decided to try the following although I wanted a much 'prettier' solution.
FILTER (?date >= "2014-08-15T00:00:00Z"^^xsd:dateTime && ?date <= "2014-08-15T24:00:00Z"^^xsd:dateTime)
You can do this, but not exactly the way your question asks. The literal forms for dateTimes have to have all the fields (except the timezone), so "2014-08-15"^^xsd:dateTime isn't actually a legal dateTime. See the definition for more about the date time format.
That said, it's easy enough to pull out the year, month, and day from a datetime and put them back together into a date that you can compare with other dates:
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?dt ?date where {
values ?dt { "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime }
bind(xsd:date(concat(str(year(?dt)),"-",
str(month(?dt)),"-",
str(day(?dt))))
as ?date)
}
--------------------------------------------------------------------------
| dt | date |
==========================================================================
| "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime | "2011-01-10"^^xsd:date |
--------------------------------------------------------------------------
If you want to include the timezone, you can do that too; they're permitted in xsd:dates.
If you wanted to filter without creating the new date, you could also do something like
filter (year(?dt) = 2015 &&
month(?dt) = 01 &&
day(?dt) = 10)
That might be a fairly clean solution.
A note about your filter, though. You can filter the value of a variable against a constant like you did, but that often (but not always) suggests an easier way. For instance, instead of:
select ?s where {
?s a ?o .
filter ( ?o = <something> )
}
you'd usually just use the value in place, or use values to specify the value of a variable:
select ?s where {
?s a <something> .
}
select ?s where {
values ?o { <something> }
?s a ?o .
}
You could try a simple cast to xsd:date, but the SPARQL engine will likely retain the time. So it becomes a matter of parsing. One way is to just use SUBSTR, as the number of characters is known:
FILTER (xsd:date(SUBSTR(str(?date), 0, 11)) = "2014-08-15"^^xsd:date)
Another is to build the date from datetime format:
FILTER (xsd:date(CONCAT(str(YEAR(?date)), "-", str(MONTH(?date)), "-", str(DAY(?date)))) = "2014-08-15"^^xsd:date)
Perhaps not as convenient given that CONCAT requires string conversion, but the general idea is to build the string from the datetime value and cast to xsd:date.