How to get film cost currency in Wikidata SPARQL? - sparql

I know how to get the cost of specified films:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?item (GROUP_CONCAT( ?_cost; SEPARATOR = "~~~") AS ?budget)
WHERE {
VALUES ?selectedMovies { wd:Q24515019 wd:Q20762698 }
?item wdt:P31/wdt:P279* wd:Q11424 filter (?item = ?selectedMovies).
OPTIONAL {
?item wdt:P2130 ?_cost.
}
}
GROUP BY ?item
But when I try to get the currency for cost, I get nothing:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?item (GROUP_CONCAT( ?_cost; SEPARATOR = "~~~") AS ?budget)
(GROUP_CONCAT( ?_currency; SEPARATOR = "~~~") AS ?_currency)
WHERE {
VALUES ?selectedMovies { wd:Q24515019 wd:Q20762698 }
?item wdt:P31/wdt:P279* wd:Q11424 filter (?item = ?selectedMovies).
OPTIONAL {
?item wdt:P2130 ?_cost.
?_cost wdt:P2237 ?_currency.
}
}
GROUP BY ?item
I checked, on the page of these movies, the cost currency is present.
So, how can I get the currency?

Well, it's a bit more complicated as you're asking for properties of units:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?item (GROUP_CONCAT( DISTINCT ?cost_with_unit; SEPARATOR = "~~~") AS ?budget)
WHERE {
VALUES ?selectedMovies { wd:Q24515019 wd:Q20762698 }
?item wdt:P31/wdt:P279* wd:Q11424 filter (?item = ?selectedMovies).
OPTIONAL {
?item wdt:P2130 ?_cost.
# get the node to the cost statement
?item p:P2130 ?stmnode.
# then its value node
?stmnode psv:P2130 ?valuenode.
# then its unit, i.e. currency as entity
?valuenode wikibase:quantityUnit ?unit.
# then finally, its label
?unit rdfs:label ?unitLabel.
FILTER(LANGMATCHES(LANG(?unitLabel), 'en'))
# put everything together
BIND(CONCAT(str(?_cost), " ", str(?unitLabel)) as ?cost_with_unit)
}
}
GROUP BY ?item
Update
To get the ISO 4217 code of the unit, replace
# then finally, its label
?unit rdfs:label ?unitLabel.
FILTER(LANGMATCHES(LANG(?unitLabel), 'en'))
with
# then finally, the ISO 4217 code of the unit, e.g. USD
?unit wdt:P498 ?unitLabel .

Related

How to get the Wikidata ID (Q…) using just a label?

Is there any way to get the Wikidata Q identifier of an entity using just the label as a string?
For example, "Java":
Q251
I want to search only the English labels.
PREFIX wd: <http://www.wikidata.org/entity/>
SELECT DISTINCT ?qid
WHERE {
# make input string into a language-tagged string
BIND( STRLANG("Java", "en") AS ?label ) .
# search all items that have this languaged-tagged string as label
?item rdfs:label ?label .
# extract the last path segment of the URI
BIND(STRAFTER(STR(?item), STR(wd:)) AS ?qid) .
}
If you can append #en to the input string ("Java"#en), you can use:
PREFIX wd: <http://www.wikidata.org/entity/>
SELECT DISTINCT ?qid
WHERE {
?item rdfs:label "Java"#en .
BIND(STRAFTER(STR(?item), STR(wd:)) AS ?qid) .
}
If you are fine with the URI (e.g., http://www.wikidata.org/entity/Q251) instead of the QID (e.g., Q251) as result, you can use:
SELECT DISTINCT ?item
WHERE {
?item rdfs:label "Java"#en .
}
If you want to ignore case, you can use UCASE or LCASE in a FILTER.

Get information using python, SPARQL ,DBpedia and Wikidata

I have a CSV file with a list of names in English and Hebrew, I need to get some information on.
The data I need is
"name-Hebrew name-English DBpedia-URL date birth place birth dateDeath placeDeath entry_where_found"
for each person, the "entry_where_found" should return if I found the information on DBpedia or wiki data.
I thought of something like this:
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?person WHERE {
SERVICE <http://dbpedia.org/sparql> {?person a dbo:Person }
SERVICE <https://query.wikidata.org/sparql> { ?person wdt:P31 wd:Q5 }
}
to query both DBpedia and wikidata, and something like this:
SELECT ?instance_of ?label_he ?label_en ?place_of_birthLabel ?date_of_birth ?place_of_death ?place_of_deathLabel ?date_of_death ?URL WHERE {
?instance_of rdfs:label ?label_he.
?instance_of rdfs:label ?label_en.
?instance_of wdt:P31 wd:Q5.
?instance_of wdt:P19 ?place_of_birth.
?instance_of wdt:P569 ?date_of_birth.
?instance_of wdt:P20 ?place_of_death.
?instance_of wdt:P570 ?date_of_death.
OPTIONAL { ?instance_of wdt:P31 ?record_label. }
OPTIONAL { ?instance_of wdt:P31 ?instance_of. }
OPTIONAL { ?instance_of wdt:P2699 ?URL. }
FILTER(((LANG(?label_he)) = "he") && ((LANG(?label_en)) = "en"))
}
But I don't know how to add a specific name to find each time, and how to combine the query with the first code.
Can someone help?
Thank You!

sparql exclude multiple type hierarchy

In dbpedia I select some pages with label starting 'A'. Here I'm using additional filter by subject to narrow the set. In original version there are another conditions (result set is much bigger)
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX purl: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://dbpedia.org/page/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX dbr: <http://dbpedia.org/resource/>
SELECT DISTINCT
?pageType
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
}
FILTER ( strstarts(str(?pageType), 'http://dbpedia.org/ontology') )
}
LIMIT 1000
sparql results
Here I select only page types to be clear with rest of the question.
This is the whole set. Now I want to exclude some pages. Exclude all agents (persons, organization etc):
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX purl: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://dbpedia.org/page/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX dbr: <http://dbpedia.org/resource/>
SELECT DISTINCT
?pageType
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent }
}
FILTER ( strstarts(str(?pageType), 'http://dbpedia.org/ontology') )
}
LIMIT 1000
The result.
Ok. Then I want to exclude more types, for example Written_Work. I tried different approaches, but unabled to find the correct one.
This returns nothing:
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent }
MINUS { ?page a dbo:WrittenWork }
}
This is like no filter is set:
WHERE
{
{
?page rdfs:label ?label .
?page a ?pageType .
?page <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Banking> .
MINUS { ?page a dbo:Agent, dbo:WrittenWork }
}
The question is:
what way should I go to exclude pages of certain types (direct and superclass)?
It look's like this is working answer (how to exclude multiple of types)
{
?page purl:subject ?id .
?page a ?pageType .
FILTER NOT EXISTS {
?page a/rdfs:subClassOf* ?skipClasses .
FILTER(?skipClasses in (dbo:Agent, dbo:Place, dbo:Work))
}
}
In this example all dbo:Agents, db:Places, dbo:Works will be filtered out.

SPARQL BIND inside UNION is too slow

Given an IMDb ID, i want to get a list of directors and actors for that movie from Wikidata.
The problem is, I want to UNION both the director and actor query into a single column while also providing a new column with the role of director or actor.
Pretty easy query overall: first I get the movie entity from the IMDb ID, then I get all the directors from that movie followed by getting all the actors from that movie and UNION them together while filling a new column (?role) with the role.
This is what I have:
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
?movie wdt:P345 "tt0110912" .
{ ?movie p:P57 ?cast .
?cast ps:P57 ?person .
BIND("director" as ?role) .
} UNION {
?movie p:P161 ?cast .
?cast ps:P161 ?person .
BIND("actor" as ?role) . }
?person wdt:P345 ?imdb .
OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100
This works and gives the result I want, problem is it takes about 10secs. If I remove the BINDs its instant speed, but I don't get a column with the roles.
I'd write this using values instead of bind and union. The idea is that you're saying when the properties are one thing, then ?role is one thing, and when the properties are another, ?role is another. The easy way to do that with values is something like:
select ?owner ?pet ?petType {
values (?hasPet ?petType) {
(:hasCat "cat")
(:hasDog "dog")
}
?owner ?hasPet ?pet
}
In your case, this would be:
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
?movie wdt:P345 "tt0110912" .
values (?p ?ps ?role) {
(p:P161 ps:P161 "actor")
(p:P57 ps:P57 "director")
}
?movie ?p ?cast .
?cast ?ps ?person .
?person wdt:P345 ?imdb .
OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100
When I run this at query.wikidata.org, it produces 35 results almost instantly.
I guess that BIND leads to some problems with the query optimizer. You can try as an alternative to bind the role outside of the UNION clause, i.e.
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?person ?personLabel ?role ?imdb WHERE
{
?movie wdt:P345 "tt0110912" .
?person wdt:P345 ?imdb .
{
?movie p:P57 ?c1 . ?c1 ps:P57 ?person .
?movie p:P57 ?cast .
} UNION {
?movie p:P161 ?c2 . ?c2 ps:P161 ?person .
?movie p:P161 ?cast .
}
BIND(IF(bound(?c1), "director", "actor") as ?role)
OPTIONAL { ?cast prov:wasDerivedFrom ?ref . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?person ?personLabel ?role ?imdb
ORDER BY DESC(?role)
LIMIT 100
(If you do not the ?ref variable, you can omit the triple patterns to retrieve the ?cast in the UNION clauses.)

How to SPARQL optional

I have to use this Spaql query to retrive information about a person, my problem is to break the optional construct up into multiple optional constructs.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbpprop: <http://dbpedia.org/property/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?label ?abstract ?placeOfBirth
?birthPlace ?birthDate ?page ?thumbnail
WHERE {
<http://dbpedia.org/resource/Ismail_Kadare> rdfs:label ?label ;
dbo:abstract ?abstract ;
foaf:page ?page .
OPTIONAL {
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth ;
dbpprop:birthPlace ?birthPlace ;
dbo:birthDate ?birthDate ;
dbo:thumbnail ?thumbnail .
}
FILTER (LANG(?label) = 'en')
FILTER (LANG(?abstract) = 'en')
}
LIMIT 1
Splitting the OPTIONAL pattern into parts
The pattern
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth ;
dbpprop:birthPlace ?birthPlace ;
dbo:birthDate ?birthDate ;
dbo:thumbnail ?thumbnail .
is shorthand for four triple patterns:
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth .
<http://dbpedia.org/resource/Ismail_Kadare> dbpprop:birthPlace ?birthPlace .
<http://dbpedia.org/resource/Ismail_Kadare> dbo:birthDate ?birthDate .
<http://dbpedia.org/resource/Ismail_Kadare> dbo:thumbnail ?thumbnail .
Instead of OPTIONAL { …first pattern… }, you just need to use four optional blocks, one for each of the four triple patterns:
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbpprop:placeOfBirth ?placeOfBirth }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbpprop:birthPlace ?birthPlace }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbo:birthDate ?birthDate }
optional { <http://dbpedia.org/resource/Ismail_Kadare> dbo:thumbnail ?thumbnail }
Other issues
It's worth nothing that language matching is a bit more complicated than string matching, so rather than
FILTER (LANG(?label) = 'en')
FILTER (LANG(?abstract) = 'en')
you should really be using
filter(langMatches(lang(?label),'en'))
filter(langMatches(lang(?abstract),'en'))
which allows you to retrieve results that use different language tags that are all English.
select distinct and limit 1 aren't both necessary
Notice that select distinct ensures that you don't have any duplicate rows in your results. However, limit 1 means that you'll only have one result at most anyhow, so there won't be any duplicates to remove.
Standard Namespaces
It looks like you're querying against DBpedia, so it might be worthwhile to use the same namespace prefixes that the public endpoint defines, so that you can copy and paste queries and experiment more easily. Doing that (and using a values ?x { dbpedia:Ismail_Kadare } to avoid some typing, we end up with this query:
select ?label ?abstract ?placeOfBirth ?birthPlace ?birthDate ?page ?thumbnail
where {
values ?x { dbpedia:Ismail_Kadare }
?x rdfs:label ?label ;
dbpedia-owl:abstract ?abstract ;
foaf:page ?page .
optional { ?x dbpprop:placeOfBirth ?placeOfBirth }
optional { ?x dbpprop:birthPlace ?birthPlace }
optional { ?x dbpedia-owl:birthDate ?birthDate }
optional { ?x dbpedia-owl:thumbnail ?thumbnail }
filter langMatches(lang(?label),'en')
filter langMatches(lang(?abstract),'en')
}
limit 1
The DBpedia endpoint won't return anything for that query, but that's because http://dbpedia.org/resource/Ismail_Kadare doesn't have a foaf:page property, not because the query is malformed. I don't know whether you're actually running this against DBpedia or not, so that may or not matter.