Filter data with subquery in SPARQL - sparql

I'm trying to get some data from Wikidata. I've got a simple query which fetches information about universities:
SELECT ?item ?itemLabel ?site WHERE {
?item (p:P31/ps:P31/(wdt:P279*)) wd:Q38723;
wdt:P17 ?country;
wdt:P856 ?site.
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". }
}
And another query, which gets list of members of the CIS:
SELECT DISTINCT ?state WHERE {
?state wdt:P31/wdt:P279* wd:Q3624078;
p:P463 ?memberOfStatement.
?memberOfStatement a wikibase:BestRank;
ps:P463 wd:Q7779
MINUS { ?memberOfStatement pq:P582 ?endTime. }
MINUS { ?state wdt:P576|wdt:P582 ?end. }
}
Both work fine. But now I want to combine them to get list of universities which are located in the CIS. I try to do it like shown in the answer to this question:
SELECT ?item ?itemLabel ?site WHERE {
?item (p:P31/ps:P31/(wdt:P279*)) wd:Q38723;
wdt:P17 ?country;
wdt:P856 ?site.
FILTER(EXISTS {
SELECT DISTINCT ?state WHERE {
{
?state (wdt:P31/(wdt:P279*)) wd:Q3624078;
p:P463 ?memberOfStatement.
?memberOfStatement rdf:type wikibase:BestRank;
ps:P463 wd:Q7779.
MINUS { ?memberOfStatement pq:P582 ?endTime. }
MINUS { ?state (wdt:P576|wdt:P582) ?end. }
}
FILTER(?country = ?state)
}
})
SERVICE wikibase:label { bd:serviceParam wikibase:language "ru,en". }
}
But, for some reason, I get zero results. What am I doing wrong here?

Related

Grouping qualifiers in the output of a Wikidata SPARQL query

I am building a Wikidata SPARQL query to retrieve details about specific people. When asking for their educational details (P69 - educatedAt)- I am not sure how to craft the query such that it will collate their degrees and majors in the case that in one statement about being educated at an institution they have multiple degrees or majors (I used this other query to find people with multiple degrees from Harvard).
This is the query:
SELECT ?itemLabel (GROUP_CONCAT(DISTINCT ?altNames; SEPARATOR = ";") AS ?aliases) ?itemDesc ?genderLabel ?birthday ?placeOfBirthLabel ?image (GROUP_CONCAT(DISTINCT ?ed; SEPARATOR = "|") AS ?education) WHERE {
VALUES ?item {
wd:Q5402996
}
OPTIONAL {
?item skos:altLabel ?altNames.
FILTER((LANG(?altNames)) = "en")
}
{
OPTIONAL { ?item wdt:P21 ?gender. }
OPTIONAL { ?item wdt:P569 ?birthday. }
OPTIONAL { ?item wdt:P19 ?placeOfBirth. }
OPTIONAL { ?item wdt:P18 ?image. }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
{
OPTIONAL {
?item p:P69 ?statement.
?statement (ps:P69/rdfs:label) ?eduLabel.
FILTER((LANG(?eduLabel)) = "en")
OPTIONAL { ?statement pq:P580 ?edStart. }
OPTIONAL { ?statement pq:P582 ?edEnd. }
OPTIONAL {
?statement (pq:P512/rdfs:label) ?edDegrees.
FILTER((LANG(?edDegrees)) = "en")
}
OPTIONAL {
?statement (pq:P812/rdfs:label) ?edMajors.
FILTER((LANG(?edMajors)) = "en")
}
BIND(IF(BOUND(?edStart), CONCAT("::start:", STR(YEAR(?edStart))), "") AS ?edStartText)
BIND(IF(BOUND(?edEnd), CONCAT("::end:", STR(YEAR(?edEnd))), "") AS ?edEndText)
BIND(IF(BOUND(?edDegrees), CONCAT("::degrees:", STR(?edDegrees)), "") AS ?edDegreeText)
BIND(IF(BOUND(?edMajors), CONCAT("::majors:", STR(?edMajors)), "") AS ?edMajorText)
BIND(CONCAT(?eduLabel, ?edStartText, ?edEndText, ?edDegreeText, ?edMajorText) AS ?ed)
}
}
SERVICE wikibase:label {
bd:serviceParam wikibase:language "en".
?item schema:description ?itemDesc.
}
}
GROUP BY ?itemLabel ?itemDesc ?genderLabel ?birthday ?image ?placeOfBirthLabel
For the education result I get:
Harvard University::end:1980::degrees:Master of Arts::majors:astronomy|
Harvard University::end:1980::degrees:Doctor of Philosophy::majors:astronomy|
University of Rochester::end:1976::degrees:Bachelor of Arts|
University of Rochester::end:1976::degrees:Bachelor of Science
I would like to get:
Harvard University::end:1980::degrees:Master of Arts;Doctor of Philosophy::majors:astronomy|
University of Rochester::end:1976::degrees:Bachelor of Arts:Bachelor of Science|
How can I group the degrees in line like this in my query?
Or even better have them be nested in the JSON output rather than using delimiters?

How to return null results in SPARQL?

I'm using the Wikidata SPARQL Query Service with the following query:
SELECT ?item ?itemLabel ?class ?classLabel ?projectLabel WHERE {
VALUES ?item { wd:Q1 wd:Q367204 }
?item wdt:P31 ?class;
wdt:P18 ?project.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en,en". } }
link to the query
When running the query there is a result for Q1 because there is an image, but there is no result for Q367204 because there isn't an image.
My question: How can I get results for both Q1 and Q367204 regardless if there is an image available or not?
wd:Q367204 is missing from the results because "there isn't an image", but also because there isn't an "instance of" statement (P31). Therefore, you can get results for both instances by wrapping both of these in an OPTIONAL block, with just ?item and ?itemLabel for Q367204, and all variables for Q1:
SELECT ?item ?itemLabel ?class ?classLabel ?projectLabel WHERE {
VALUES ?item { wd:Q1 wd:Q367204 }
OPTIONAL {
?item wdt:P31 ?class;
wdt:P18 ?project.
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "en,en". }
}

BINDing to inlined data provided by VALUES, and braces

I tried the following query on WDQS:
SELECT ?item ?itemLabel ?string ?StringLabel ?iri ?iriLabel
WHERE {
VALUES ?item { wd:Q1339 }
BIND( STR(?item) AS ?string ).
BIND( IRI(?string) AS ?iri ).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
And the result has ?string and ?iri value. However, if I place an extra pair of braces in the query expression
SELECT ?item ?itemLabel ?string ?StringLabel ?iri ?iriLabel
WHERE {
VALUES ?item { wd:Q1339 }
{
BIND( STR(?item) AS ?string ).
BIND( IRI(?string) AS ?iri ).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
}
?string and ?iri in the result are empty, looking as if ?item is missing in the first BIND expression. Why is the result different?
SPARQL's "bottom-up evaluation" is often better understood by its other label, i.e., "inside-out evaluation". That is, nesting is evaluated from the innermost to the outermost.
If you flip the nesting, you'll see the results you expected --
SELECT ?item ?itemLabel ?string ?StringLabel ?iri ?iriLabel
WHERE
{
BIND( STR(?item) AS ?string ).
BIND( IRI(?string) AS ?iri ).
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
{
VALUES ?item { wd:Q1339 }
}
}

Path matching inside a VALUES clause

I'm trying to perform path matching inside a VALUES clause in sparql in order to match all instances and subclasses of both battles and sieges in wikidata. The following request repeatedly times out.
SELECT DISTINCT ?battle ?battleLabel WHERE {
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
VALUES ?type {wd:Q178561 wd:Q188055} ?battle (wdt:P31/wdt:P279*) ?type .
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
}
}
It seems that VALUES, esp. in conjunction with /, confuses the Blazegraph's query optimizer in that case.
Use UNION instead of VALUES:
SELECT DISTINCT ?battle ?battleLabel WHERE {
{ ?battle wdt:P31/wdt:P279* wd:Q178561 }
UNION
{ ?battle wdt:P31/wdt:P279* wd:Q188055 }
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }
}
Alternatively, disable the optimizer and specify explicit order:
SELECT DISTINCT ?battle ?battleLabel WHERE {
hint:Query hint:optimizer "None" .
VALUES ?type {wd:Q178561 wd:Q188055}
?subtype wdt:P279* ?type .
?battle wdt:P31 ?subtype .
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }
}

Wikidata: list every physical objects

I'm trying to get the name of the all physical things (tangible concepts) Wikidata knows about (objects, places, countries, etc), or in other words everything non-abstract.
There are examples close to what I need, but with only a depth of one: all the things that are instances of phone.
I found this example that searches with more depth and I modified the start point to entity:
#Children of Genghis Khan
#added before 2016-10
#defaultView:Graph
PREFIX gas: <http://www.bigdata.com/rdf/gas#>
SELECT ?item ?itemLabel ?pic ?linkTo
WHERE
{
SERVICE gas:service {
gas:program gas:gasClass "com.bigdata.rdf.graph.analytics.SSSP" ;
gas:in wd:Q35120 ;
gas:traversalDirection "Forward" ;
gas:out ?item ;
gas:out1 ?depth ;
gas:maxIterations 4 ;
gas:linkType wdt:279 .
}
OPTIONAL { ?item wdt:P40 ?linkTo }
OPTIONAL { ?item wdt:P18 ?pic }
SERVICE wikibase:label {bd:serviceParam wikibase:language "en" }
}
I still get no results.
As mentionned in a comment, your question is too broad and you'll end up with too much answers
You look for the A that are instance of a subclass of B
so the query you point to is the right one
SELECT DISTINCT ?item
WHERE {
?item wdt:P31/wdt:P279* wd:Q35120
}
the problem is the size
wd:Q35120 has a lot of subclasses
You can check that this way
SELECT ?a ?aLabel WHERE { ?a wdt:P279 wd:Q35120.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
SELECT ?a ?aLabel WHERE { ?a wdt:P279/wdt:P279? wd:Q35120.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
SELECT ?a ?aLabel WHERE { ?a wdt:P279/wdt:P279?/wdt:P279? wd:Q35120.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
And so on : you'll see that there are already 40'000+ at forth level which is huge
You could also huge this nice tool to have a more precise view
https://tools.wmflabs.org/bambots/WikidataClasses.php?id=Q35120&lang=en