I am trying to make some sparql query statement with python programming and I got stuck below. What I am trying to make is query statement of the time range somehow general manner. Give me an example below. Question is "Who was the mayor of the new york city in %(YEAR)?" and corresponding sparql I write is same as below. For the far previous range, it works okay. But the recent range, it doesn't work because the current mayor does not have end time. In other words, can I make a code something like FIlTER (?v3 has no value or ?v3 > "2011-01-01"^^xsd:dateTime) ? I'd like to improve my sparql with one query in more general manner corresponding to the time range questions.
CASE 1: Who was the mayor of the new york city in 2011? -ok
SELECT DISTINCT ?v ?vLabel ?v2 ?v3
WHERE
{
wd:Q60 p:P6 ?stmt.
?stmt ps:P6 ?v;
pq:P580 ?v2;
pq:P582 ?v3.
FILTER (?v2 < "2011-01-01"^^xsd:dateTime) # start time
FILTER (?v3 > "2011-01-01"^^xsd:dateTime) # end time
SERVICE wikibase:label { bd:serviceParam wikibase:language "ko,en". }
}
ORDER BY DESC (?v2)
CASE 2: Who was the mayor of the new york city in 2016? - No answer
SELECT DISTINCT ?v ?vLabel ?v2 ?v3
WHERE
{
wd:Q60 p:P6 ?stmt.
?stmt ps:P6 ?v;
pq:P580 ?v2;
pq:P582 ?v3
FILTER (?v2 < "2016-01-01"^^xsd:dateTime) # start time
FILTER (?v3 > "2016-01-01"^^xsd:dateTime) # end time
SERVICE wikibase:label { bd:serviceParam wikibase:language "ko,en". }
}
ORDER BY DESC (?v2)
Step 1: Get the query pattern to match even if there is no value for “end time”. This can be done using OPTIONAL for that triple pattern:
OPTIONAL { ?stmt pq:P582 ?v3 }
Step 2: Change the filter so that it accepts solutions where the end time variable ?v3 has no value. This can be done using the bound function, which returns true if there is a value and false otherwise:
FILTER (!bound(?v3) || ?v3 > "2016-01-01"^^xsd:dateTime) # end time
Complete query:
SELECT DISTINCT ?v ?vLabel ?v2 ?v3
WHERE
{
wd:Q60 p:P6 ?stmt.
?stmt ps:P6 ?v;
pq:P580 ?v2.
OPTIONAL { ?stmt pq:P582 ?v3 }
FILTER (?v2 < "2016-01-01"^^xsd:dateTime) # start time
FILTER (!bound(?v3) || ?v3 > "2016-01-01"^^xsd:dateTime) # end time
SERVICE wikibase:label { bd:serviceParam wikibase:language "ko,en". }
}
ORDER BY DESC (?v2)
Related
I want to write a SPARQL query that would return the first name of a person based on the ranking of the name on Wikidata.
For example, let's say I want the second first name of Mozart (Chrysostom).
This is what I have so far (Mozart Wikidata ID is Q254, first name's property is P735, with P1545 giving the ordinal position of the name):
SELECT DISTINCT ?full_name ?full_nameLabel ?first_nameLabel ?rank
WHERE
{
VALUES ?full_name {wd:Q254} .
?full_name p:P735 [pq:P1545 ?rank] ;
p:P735 [ps:P735 ?first_name] ;
FILTER regex(?rank, "2")
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
However here the filter only applies to the rank variable, and not on the first_name variable:
Query result:
I think that the problem comes from the fact that the rank property is a sub-element of the first_name property. Would you know of a way to filter the first_name variable by the rank variable?
SELECT DISTINCT ?id ?idLabel ?first_nameLabel ?rank
WHERE {
VALUES ?id {wd:Q254} .
?id p:P735 [
pq:P1545 ?rank;
ps:P735 ?first_name
]
FILTER(?rank = "2")
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
I want a list of all currencies by El Salvador with their subdivision.
I use this query:
SELECT ?currency ?currencyLabel ?currencyIso4217 ?subdivisionLabel {
?currency wdt:P498 ?currencyIso4217 .
?currency wdt:P9059 ?subdivision .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
{
?country wdt:P38 ?currency .
BIND(wd:Q792 AS ?country).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
}
Try it here: Link
This gives the following result:
Works perfectly. But row 2 and three are the same currency. That currency only uses multiple names for the subdivision. I want them to concat so I get this output:
Is that possible?
Grouping in SPARQL works similar to SQL.
The function GROUP BY combines results that have identical values into groups. Afterwards, an aggregate function is applied to the other (non-identical) values for each group.
Typical aggregate functions are COUNT, SUM, MIN, MAX, AVG, GROUP_CONCAT, and SAMPLE.
For you GROUP_CONCAT is of interest. It performs a string concatenation across the values of a group. With the argument separator you can even specify a separator character. The order of the strings is arbitrary.
The syntax of GROUP BY and GROUP_CONCAT was already given to you in the comment by UninformedUser but I repeat it here in a slightly adapted form:
SELECT ?currency ?currencyLabel ?currencyIso4217 (GROUP_CONCAT(?subdivisionLabel; separator = ", ") as ?subdivisionLabels) {
BIND(wd:Q792 AS ?country).
?country wdt:P38 ?currency .
?currency wdt:P498 ?currencyIso4217 .
?currency wdt:P9059 ?subdivision .
?subdivision rdfs:label ?subdivisionLabel .
FILTER(lang(?subdivisionLabel) = 'en')
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} GROUP BY ?currency ?currencyLabel ?currencyIso4217
What I am trying to do is to select a certain entity for the certain condition. If the condition is url, then how I can make a proper query to get the only result that matches the v1 = "https://www.getmagicbullet.com/" .
The commented sentences are what I tried different ways, but only to fail. How could I adjust the query to get the right answer?
Thank you for your help.
SELECT DISTINCT ?iLabel ?p ?v1
WHERE {
?i wdt:P31 wd:Q212920.
?i wdt:P856 ?v1.
# FILTER (?v1Label = "https://www.getmagicbullet.com/")
# { ?v1 rdfs:label "https://www.getmagicbullet.com/"#en }
# UNION { ?v1 skos:altLabel "https://www.getmagicbullet.com/"#en }
SERVICE wikibase:label { bd:serviceParam wikibase:language "ko,en,[AUTO_LANGUAGE]". }
}
LIMIT 1000
I have the following SPARQL query that appears to correctly produce the films produced in the US (country of origin) and released in the US (place of publication) in 2018. The issue I'm having is that one row is produced for each release even though the other releases are outside of the US. I've added a limit to reduce the size of the response.
Here is the query:
SELECT ?item ?name ?publication_date ?placeLabel WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item rdfs:label ?name;
wdt:P31 wd:Q11424;
wdt:P495 wd:Q30; # -> country of origin US
wdt:P577 ?publication_date.
?item p:P577 ?publication_statement.
?publication_statement pq:P291 ?place.
FILTER(xsd:date(?publication_date) > "2018-01-01"^^xsd:date)
FILTER(
(LANG(?name)) = "en"
&& ?place=wd:Q30) # -> place of publication
}
ORDER BY ?name
LIMIT 10
I would like to change it so that it produces one row per movie IF it had a release in the US in 2018.
Thanks for your help. Comments on the use of FILTER or other non idiomatic SPARQL are also welcome.
You can use GROUP BY:
SELECT ?item (SAMPLE(?name) as ?Name) (SAMPLE(?publication_date) as ?Date) WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item rdfs:label ?name;
wdt:P31 wd:Q11424;
wdt:P495 wd:Q30; # -> country of origin US
wdt:P577 ?publication_date.
?item p:P577 ?publication_statement.
?publication_statement pq:P291 ?place.
FILTER(xsd:date(?publication_date) > "2018-01-01"^^xsd:date)
FILTER(
(LANG(?name)) = "en"
&& ?place=wd:Q30) # -> place of publication
}
GROUP BY ?item
ORDER BY ?Name
LIMIT 10
See this query on Wikidata.
And you need to fix the SELECT line as you can't pass out the indeterminate non-group keys without explicitly saying. See similar question.
I wanted to add the instance of property to this example query to get only items which are an instance of human.
This is the example query:
SELECT ?entityLabel (YEAR(?date) as ?year)
WHERE
{
BIND(MONTH(NOW()) AS ?nowMonth)
BIND(DAY(NOW()) AS ?nowDay)
?entity wdt:P569 ?date .
FILTER (MONTH(?date) = ?nowMonth && DAY(?date) = ?nowDay)
SERVICE wikibase:label {
bd:serviceParam wikibase:language "en" .
}
}
LIMIT 10
And this my adjusted version with the instance of property:
SELECT ?entityLabel (YEAR(?date) as ?year)
WHERE
{
?entity wdt:P31 wd:Q5 .
BIND(MONTH(NOW()) AS ?nowMonth)
BIND(DAY(NOW()) AS ?nowDay)
?entity wdt:P569 ?date .
FILTER (MONTH(?date) = ?nowMonth && DAY(?date) = ?nowDay)
SERVICE wikibase:label {
bd:serviceParam wikibase:language "en" .
}
}
LIMIT 10
But also I added just the one line I now get a query timeout.
Does anyone know how I cloud improve my query so that I don't get a timeout.
This will time out because the query service will attempt to start with all wdt:P31 wd:Q5 before limiting them.
You can see more details in:
https://www.wikidata.org/wiki/Wikidata:SPARQL_query_service/query_optimization