Cheatsheets:SPARQL: Difference between revisions
Replace escaped placeholder tag with inline code formatting (via update-page on MediaWiki MCP Server) Tag: Replaced |
Restore full page with CONSTRUCT inline-code fix (previous edit sent only a fragment) (via update-page on MediaWiki MCP Server) |
||
| Line 1: | Line 1: | ||
{{Cheatsheet}} | |||
SPARQL 1.1 quick syntax reference — for people who already know what SPARQL is | |||
and need reminders on syntax. All examples run as-is against the public | |||
Wikidata endpoint <syntaxhighlight lang="text" inline>https://query.wikidata.org/sparql</syntaxhighlight>. | |||
For a proper tutorial, take the | |||
[https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial]. | |||
For querying a different Wikibase instance (endpoint, prefixes, label service), | |||
see [[Help:Contributing/query]]. | |||
== Building a query == | |||
Every query is built from '''triple patterns''': <syntaxhighlight lang="sparql" inline>subject predicate object .</syntaxhighlight> | |||
A triple states one fact about the data; a query joins several triples to answer a | |||
question. You usually know two of the three parts and query the third: | |||
{| class="wikitable" | |||
! Question !! Known parts !! Pattern | |||
|- | |||
| "What is the population of France?" || subject France (wd:Q142) + predicate population (wdt:P1082) || <syntaxhighlight lang="sparql" inline>wd:Q142 wdt:P1082 ?population .</syntaxhighlight> | |||
|- | |||
| "Which things are dogs?" || predicate instance-of (wdt:P31) + object dog (wd:Q144) || <syntaxhighlight lang="sparql" inline>?x wdt:P31 wd:Q144 .</syntaxhighlight> | |||
|- | |||
| "What is known about Einstein?" || subject Einstein (wd:Q937) || <syntaxhighlight lang="sparql" inline>wd:Q937 ?predicate ?value .</syntaxhighlight> | |||
|} | |||
Write the question in this order and the query writes itself: | |||
<syntaxhighlight lang="sparql"> | |||
# "What is the population of France?" | |||
SELECT ?population WHERE { | |||
wd:Q142 wdt:P1082 ?population . | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
68605616 | |||
</syntaxhighlight> | |||
Values can be: | |||
* '''IRIs''' — entities (wd:Q144), properties (wdt:P31), other resources | |||
* '''Literals''' — typed values or language-tagged strings: <syntaxhighlight lang="sparql" inline>"42"^^xsd:integer</syntaxhighlight>, <syntaxhighlight lang="sparql" inline>"2026-08-19"^^xsd:date</syntaxhighlight>, <syntaxhighlight lang="sparql" inline>"dog"@en</syntaxhighlight>, <syntaxhighlight lang="sparql" inline>"chien"@fr</syntaxhighlight> | |||
* '''Blank nodes''' — <syntaxhighlight lang="sparql" inline>[]</syntaxhighlight> or <syntaxhighlight lang="sparql" inline>_:x</syntaxhighlight>: "some unnamed thing", not an IRI | |||
<blockquote>'''Gotcha:''' blank-node labels (<syntaxhighlight lang="sparql" inline>_:x</syntaxhighlight>) are local to one query — they are not IRIs and cannot be referenced across queries.</blockquote> | |||
<blockquote>'''Gotcha:''' the prefixes <syntaxhighlight lang="sparql" inline>wd:</syntaxhighlight>/<syntaxhighlight lang="sparql" inline>wdt:</syntaxhighlight> are Wikidata's; other instances define their own (see [[Help:Contributing/query]]).</blockquote> | |||
== Query forms == | |||
{| class="wikitable" | |||
! Form !! Returns !! Use when | |||
|- | |||
| SELECT || table of variable bindings || you want rows of data | |||
|- | |||
| ASK || true/false || you only need to know whether something exists | |||
|- | |||
| CONSTRUCT || an RDF graph (triples) || you want the result as RDF, not a table | |||
|- | |||
| DESCRIBE || a graph describing the resource || you want everything known about an entity | |||
|} | |||
'''SELECT''' — what is the population of France? | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?population WHERE { | |||
wd:Q142 wdt:P1082 ?population . | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
68605616 | |||
</syntaxhighlight> | |||
'''ASK''' — is there at least one dog in Wikidata? | |||
<syntaxhighlight lang="sparql"> | |||
ASK WHERE { ?x wdt:P31 wd:Q144 . } | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
true | |||
</syntaxhighlight> | |||
'''CONSTRUCT''' — every dog as RDF (first two). Each result row becomes a | '''CONSTRUCT''' — every dog as RDF (first two). Each result row becomes a | ||
triple <syntaxhighlight lang="sparql" inline>?x wdt:P31 wd:Q144</syntaxhighlight>: | triple <syntaxhighlight lang="sparql" inline>?x wdt:P31 wd:Q144</syntaxhighlight>: | ||
| Line 12: | Line 99: | ||
Q280571 wdt:P31 wd:Q144 | Q280571 wdt:P31 wd:Q144 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''DESCRIBE''' — everything known about Einstein (all triples with wd:Q937 as | |||
subject or object): | |||
<syntaxhighlight lang="sparql"> | |||
DESCRIBE wd:Q937 | |||
</syntaxhighlight> | |||
Result (visualised, N-Triples style, first few of thousands): | |||
<syntaxhighlight lang="text"> | |||
Q937 rdfs:label "Albert Einstein"@en | |||
Q937 wdt:P569 1879-03-14 | |||
Q937 wdt:P570 1955-04-18 | |||
Q937 wdt:P21 wd:Q6581097 # male | |||
</syntaxhighlight> | |||
== Solution modifiers == | |||
Each modifier shown without / with, side by side. | |||
'''DISTINCT''' — drop duplicate rows. Einstein and Obama are both male, so the | |||
gender repeats: | |||
{| class="wikitable" | |||
! Without !! With DISTINCT | |||
|- | |||
| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?genderLabel WHERE { | |||
VALUES ?person { wd:Q937 wd:Q76 } | |||
?person wdt:P21 ?gender . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
male | |||
male | |||
</syntaxhighlight> | |||
|| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT DISTINCT ?genderLabel WHERE { | |||
VALUES ?person { wd:Q937 wd:Q76 } | |||
?person wdt:P21 ?gender . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
male | |||
</syntaxhighlight> | |||
|} | |||
Diff: | |||
<syntaxhighlight lang="diff"> | |||
SELECT ?genderLabel WHERE { | |||
VALUES ?person { wd:Q937 wd:Q76 } | |||
?person wdt:P21 ?gender . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
+DISTINCT | |||
</syntaxhighlight> | |||
'''ORDER BY + LIMIT''' — the 3 most populous countries, sorted descending: | |||
{| class="wikitable" | |||
! Without (arbitrary order) !! With ORDER BY DESC + LIMIT | |||
|- | |||
| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } # China, US, India | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
United States 340110988 | |||
China 1404890000 | |||
India 1326093247 | |||
</syntaxhighlight> | |||
|| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
ORDER BY DESC(?population) | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
China 1404890000 | |||
India 1326093247 | |||
United States 340110988 | |||
</syntaxhighlight> | |||
|} | |||
Diff: | |||
<syntaxhighlight lang="diff"> | |||
SELECT ?countryLabel ?population WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
+ORDER BY DESC(?population) | |||
</syntaxhighlight> | |||
'''LIMIT''' — at most n rows: | |||
{| class="wikitable" | |||
! Without (all 3) !! With LIMIT 2 | |||
|- | |||
| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
United States | |||
China | |||
India | |||
</syntaxhighlight> | |||
|| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
LIMIT 2 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
United States | |||
China | |||
</syntaxhighlight> | |||
|} | |||
Diff: | |||
<syntaxhighlight lang="diff"> | |||
SELECT ?countryLabel WHERE { | |||
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
+LIMIT 2 | |||
</syntaxhighlight> | |||
'''OFFSET''' — skip rows (paging). The 2nd most populous country: | |||
{| class="wikitable" | |||
! With LIMIT 1 (first) !! With LIMIT 1 OFFSET 1 (second) | |||
|- | |||
| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
ORDER BY DESC(?population) | |||
LIMIT 1 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
China 1404890000 | |||
</syntaxhighlight> | |||
|| | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
ORDER BY DESC(?population) | |||
LIMIT 1 OFFSET 1 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
India 1326093247 | |||
</syntaxhighlight> | |||
|} | |||
Diff: | |||
<syntaxhighlight lang="diff"> | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
ORDER BY DESC(?population) | |||
LIMIT 1 | |||
+OFFSET 1 | |||
</syntaxhighlight> | |||
'''GROUP BY''' — covered with aggregation (see Aggregates). | |||
== FILTER == | |||
{| class="wikitable" | |||
! Category !! Operators / functions | |||
|- | |||
| comparison || = < > <= >= != | |||
|- | |||
| logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight> | |||
|- | |||
| string || STR() CONTAINS() STRSTARTS() STRENDS() REGEX() | |||
|- | |||
| numeric || ABS() ROUND() FLOOR() CEIL() | |||
|- | |||
| date/time || YEAR() MONTH() DAY() NOW() | |||
|- | |||
| term tests || isIRI() isBlank() isLiteral() LANG() DATATYPE() | |||
|} | |||
'''comparison''' — countries with more than 1 billion people: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
FILTER(?population > 1000000000) | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
China 1404890000 | |||
India 1326093247 | |||
</syntaxhighlight> | |||
'''logical (AND)''' — countries with 300M–500M people: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
FILTER(?population > 300000000 && ?population < 500000000) | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
United States 340110988 | |||
</syntaxhighlight> | |||
'''string (STRSTARTS)''' — countries whose English label starts with "S": | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country rdfs:label ?countryLabel . | |||
FILTER(LANG(?countryLabel) = "en" && STRSTARTS(?countryLabel, "S")) | |||
} | |||
LIMIT 3 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Saint Kitts and Nevis | |||
Somaliland | |||
Saint Vincent and the Grenadines | |||
</syntaxhighlight> | |||
'''numeric (ROUND)''' — France's population in millions, rounded: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?millions (ROUND(?millions) AS ?rounded) WHERE { | |||
wd:Q142 wdt:P1082 ?population . | |||
BIND(?population / 1000000 AS ?millions) | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
68.605616 69 | |||
</syntaxhighlight> | |||
'''date/time (YEAR)''' — Einstein's birth year: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?personLabel (YEAR(?birth) AS ?year) WHERE { | |||
wd:Q937 wdt:P569 ?birth . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Albert Einstein 1879 | |||
</syntaxhighlight> | |||
'''term test (isIRI)''' — the values of <syntaxhighlight lang="sparql" inline>wdt:P31</syntaxhighlight> on a dog | |||
are entities (IRIs), not literals: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?o WHERE { | |||
wd:Q144 wdt:P31 ?o . | |||
FILTER(isIRI(?o)) | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
http://www.wikidata.org/entity/Q55983715 | |||
http://www.wikidata.org/entity/Q136772238 | |||
</syntaxhighlight> | |||
<blockquote>'''Gotcha:''' an unbound variable in a FILTER makes the row fail (unbound ≠ false) — guard with <syntaxhighlight lang="sparql" inline>BOUND()</syntaxhighlight> or restructure with OPTIONAL.</blockquote> | |||
== VALUES & BIND == | |||
VALUES restricts a variable to a list; BIND computes a new variable. Together: | |||
birth years of two people, computed, not looked up: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?personLabel ?birthYear WHERE { | |||
VALUES ?person { wd:Q937 wd:Q76 } # Einstein, Obama | |||
?person wdt:P569 ?birth . | |||
BIND(YEAR(?birth) AS ?birthYear) | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Albert Einstein 1879 | |||
Barack Obama 1961 | |||
</syntaxhighlight> | |||
== Running example: dogs and cats == | |||
'''GROUP BY + COUNT + VALUES''' — how many of each animal are in Wikidata? | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?animal ?animalLabel (COUNT(?item) AS ?count) WHERE { | |||
VALUES ?animal { wd:Q144 wd:Q146 } # dog, cat | |||
?item wdt:P31 ?animal . # ?item is an instance of ?animal | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
GROUP BY ?animal ?animalLabel | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
dog 553 | |||
cat 239 | |||
</syntaxhighlight> | |||
== OPTIONAL, UNION, MINUS == | |||
{| class="wikitable" | |||
! Keyword !! Meaning | |||
|- | |||
| OPTIONAL || left join: keep the row, leave the variable unbound when absent | |||
|- | |||
| UNION || alternatives (the default between patterns is AND, not OR) | |||
|- | |||
| MINUS || remove rows that match the pattern | |||
|} | |||
'''OPTIONAL''' — Einstein (died 1955) vs Obama (alive); ?deathLabel is unbound | |||
for Obama: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?personLabel ?deathLabel WHERE { | |||
VALUES ?person { wd:Q937 wd:Q76 } # Einstein, Barack Obama | |||
OPTIONAL { ?person wdt:P570 ?death . } | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Albert Einstein 1955-04-18 | |||
Barack Obama (unbound) | |||
</syntaxhighlight> | |||
'''MINUS''' — Nobel laureates minus the French ones: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?personLabel WHERE { | |||
?person wdt:P166 wd:Q7191 . | |||
MINUS { ?person wdt:P27 wd:Q142 . } | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
LIMIT 3 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Nobel Prize winner | |||
Adam Bernau | |||
Santiago Carril | |||
</syntaxhighlight> | |||
'''UNION''' — dogs AND cats in one result set: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE { | |||
{ ?item wdt:P31 wd:Q144 . BIND("dog" AS ?animalLabel) } | |||
UNION | |||
{ ?item wdt:P31 wd:Q146 . BIND("cat" AS ?animalLabel) } | |||
} | |||
GROUP BY ?animalLabel | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
dog 553 | |||
cat 239 | |||
</syntaxhighlight> | |||
<blockquote>'''Gotcha:''' the default between triple patterns is '''AND (join)''' — use UNION for alternatives.</blockquote> | |||
<blockquote>'''Gotcha:''' <syntaxhighlight lang="sparql" inline>FILTER NOT EXISTS</syntaxhighlight> differs from <syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> when variables are unbound — prefer MINUS for set-difference semantics.</blockquote> | |||
== Property paths == | |||
{| class="wikitable" | |||
! Path !! Meaning | |||
|- | |||
| wdt:P40/wdt:P40 || two hops (sequence) | |||
|- | |||
| wdt:P40+ || one or more hops | |||
|- | |||
| wdt:P40* || zero or more hops | |||
|- | |||
| wdt:P40? || zero or one hop | |||
|- | |||
| wdt:P40|wdt:P41 || either property | |||
|- | |||
| ^wdt:P40 || inverse direction | |||
|- | |||
| !wdt:P40 || any property except P40 | |||
|} | |||
'''wdt:P31/wdt:P279*''' — named dogs, including breeds and other subclasses | |||
("instance of something that is a dog or a subclass of dog"): | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?thing ?thingLabel WHERE { | |||
?thing wdt:P31/wdt:P279* wd:Q144 . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
LIMIT 3 | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Theo | |||
Tich | |||
Tickle Em Jock | |||
</syntaxhighlight> | |||
<blockquote>'''Gotcha:''' variables used only inside a property path (e.g. <syntaxhighlight lang="sparql" inline>?s wdt:P40/wdt:P40 ?o</syntaxhighlight>) cannot be selected.</blockquote> | |||
== Aggregates == | |||
COUNT, SUM, AVG, MIN, MAX, SAMPLE (pick one arbitrary value), GROUP_CONCAT. | |||
'''HAVING''' — species with more than 400 direct instances (the running example, | |||
filtered): | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE { | |||
VALUES ?animal { wd:Q144 wd:Q146 } | |||
?item wdt:P31 ?animal . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
GROUP BY ?animal ?animalLabel | |||
HAVING (COUNT(?item) > 400) | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
dog 553 | |||
</syntaxhighlight> | |||
'''GROUP_CONCAT''' — Einstein's awards in one cell: | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?personLabel (GROUP_CONCAT(?awardLabel; SEPARATOR=", ") AS ?awards) WHERE { | |||
VALUES ?person { wd:Q937 } | |||
?person wdt:P166 ?award . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
GROUP BY ?personLabel | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
Albert Einstein Nobel Prize in Physics, … | |||
</syntaxhighlight> | |||
<blockquote>'''Gotcha:''' aggregates need GROUP BY for every non-aggregated variable; forgetting one mixes unrelated rows.</blockquote> | |||
== Subqueries == | |||
A query inside a query — useful for "the X with the max Y" patterns. | |||
'''The most populous country, computed via a subquery:''' | |||
<syntaxhighlight lang="sparql"> | |||
SELECT ?countryLabel ?max WHERE { | |||
{ | |||
SELECT (MAX(?population) AS ?max) WHERE { | |||
?c wdt:P31 wd:Q6256 . | |||
?c wdt:P1082 ?population . | |||
} | |||
} | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?max . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
</syntaxhighlight> | |||
Result: | |||
<syntaxhighlight lang="text"> | |||
China 1404890000 | |||
</syntaxhighlight> | |||
== SERVICE (labels, federation) == | |||
The label service turns entity IDs into human-readable labels — used in most | |||
queries above: | |||
<syntaxhighlight lang="sparql"> | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
# then reference ?xLabel for every ?x in the query | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="sparql"> | |||
# Federating to another endpoint (needs the remote's own IRIs, e.g. via owl:sameAs) | |||
SELECT ?cityLabel WHERE { | |||
wd:Q64 wdt:P36 ?city . | |||
?city owl:sameAs ?dbpediaCity . | |||
SERVICE <https://dbpedia.org/sparql> { | |||
?dbpediaCity rdfs:label ?cityLabel . | |||
FILTER(LANG(?cityLabel) = "en") | |||
} | |||
} | |||
</syntaxhighlight> | |||
== Further reading == | |||
* [https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial] — the recommended tutorial | |||
* [https://www.w3.org/TR/sparql11-query/ SPARQL 1.1 Query Language] — official spec | |||
* [https://query.wikidata.org/ Wikidata Query Service] — the example endpoint used here | |||
* [[Help:Contributing/query]] — querying a different instance (endpoint, prefixes, label service) | |||
Revision as of 12:20, 19 August 2026
Quick reference for smart people — part of our dev cheatsheets collection.
SPARQL 1.1 quick syntax reference — for people who already know what SPARQL is
and need reminders on syntax. All examples run as-is against the public
Wikidata endpoint https://query.wikidata.org/sparql.
For a proper tutorial, take the
Wikidata SPARQL tutorial.
For querying a different Wikibase instance (endpoint, prefixes, label service),
see Help:Contributing/query.
Building a query
Every query is built from triple patterns: subject predicate object .
A triple states one fact about the data; a query joins several triples to answer a
question. You usually know two of the three parts and query the third:
| Question | Known parts | Pattern |
|---|---|---|
| "What is the population of France?" | subject France (wd:Q142) + predicate population (wdt:P1082) | wd:Q142 wdt:P1082 ?population .
|
| "Which things are dogs?" | predicate instance-of (wdt:P31) + object dog (wd:Q144) | ?x wdt:P31 wd:Q144 .
|
| "What is known about Einstein?" | subject Einstein (wd:Q937) | wd:Q937 ?predicate ?value .
|
Write the question in this order and the query writes itself:
# "What is the population of France?"
SELECT ?population WHERE {
wd:Q142 wdt:P1082 ?population .
}
Result:
68605616
Values can be:
- IRIs — entities (wd:Q144), properties (wdt:P31), other resources
- Literals — typed values or language-tagged strings:
"42"^^xsd:integer,"2026-08-19"^^xsd:date,"dog"@en,"chien"@fr - Blank nodes —
[]or_:x: "some unnamed thing", not an IRI
Gotcha: blank-node labels (
_:x) are local to one query — they are not IRIs and cannot be referenced across queries.
Gotcha: the prefixes
wd:/wdt:are Wikidata's; other instances define their own (see Help:Contributing/query).
Query forms
| Form | Returns | Use when |
|---|---|---|
| SELECT | table of variable bindings | you want rows of data |
| ASK | true/false | you only need to know whether something exists |
| CONSTRUCT | an RDF graph (triples) | you want the result as RDF, not a table |
| DESCRIBE | a graph describing the resource | you want everything known about an entity |
SELECT — what is the population of France?
SELECT ?population WHERE {
wd:Q142 wdt:P1082 ?population .
}
Result:
68605616
ASK — is there at least one dog in Wikidata?
ASK WHERE { ?x wdt:P31 wd:Q144 . }
Result:
true
CONSTRUCT — every dog as RDF (first two). Each result row becomes a
triple ?x wdt:P31 wd:Q144:
CONSTRUCT { ?x wdt:P31 wd:Q144 . }
WHERE { ?x wdt:P31 wd:Q144 . } LIMIT 2
Result (visualised, N-Triples style):
Q186486 wdt:P31 wd:Q144
Q280571 wdt:P31 wd:Q144
DESCRIBE — everything known about Einstein (all triples with wd:Q937 as subject or object):
DESCRIBE wd:Q937
Result (visualised, N-Triples style, first few of thousands):
Q937 rdfs:label "Albert Einstein"@en
Q937 wdt:P569 1879-03-14
Q937 wdt:P570 1955-04-18
Q937 wdt:P21 wd:Q6581097 # male
Solution modifiers
Each modifier shown without / with, side by side.
DISTINCT — drop duplicate rows. Einstein and Obama are both male, so the gender repeats:
| Without | With DISTINCT |
|---|---|
SELECT ?genderLabel WHERE {
VALUES ?person { wd:Q937 wd:Q76 }
?person wdt:P21 ?gender .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result: male
male
|
SELECT DISTINCT ?genderLabel WHERE {
VALUES ?person { wd:Q937 wd:Q76 }
?person wdt:P21 ?gender .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result: male
|
Diff:
SELECT ?genderLabel WHERE {
VALUES ?person { wd:Q937 wd:Q76 }
?person wdt:P21 ?gender .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
+DISTINCT
ORDER BY + LIMIT — the 3 most populous countries, sorted descending:
| Without (arbitrary order) | With ORDER BY DESC + LIMIT |
|---|---|
SELECT ?countryLabel ?population WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 } # China, US, India
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result: United States 340110988
China 1404890000
India 1326093247
|
SELECT ?countryLabel ?population WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 }
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
Result: China 1404890000
India 1326093247
United States 340110988
|
Diff:
SELECT ?countryLabel ?population WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 }
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
+ORDER BY DESC(?population)
LIMIT — at most n rows:
| Without (all 3) | With LIMIT 2 |
|---|---|
SELECT ?countryLabel WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 }
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result: United States
China
India
|
SELECT ?countryLabel WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 }
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 2
Result: United States
China
|
Diff:
SELECT ?countryLabel WHERE {
VALUES ?country { wd:Q148 wd:Q30 wd:Q668 }
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
+LIMIT 2
OFFSET — skip rows (paging). The 2nd most populous country:
| With LIMIT 1 (first) | With LIMIT 1 OFFSET 1 (second) |
|---|---|
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 1
Result: China 1404890000
|
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 1 OFFSET 1
Result: India 1326093247
|
Diff:
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 1
+OFFSET 1
GROUP BY — covered with aggregation (see Aggregates).
FILTER
| Category | Operators / functions |
|---|---|
| comparison | = < > <= >= != |
| logical | && || !
|
| string | STR() CONTAINS() STRSTARTS() STRENDS() REGEX() |
| numeric | ABS() ROUND() FLOOR() CEIL() |
| date/time | YEAR() MONTH() DAY() NOW() |
| term tests | isIRI() isBlank() isLiteral() LANG() DATATYPE() |
comparison — countries with more than 1 billion people:
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
FILTER(?population > 1000000000)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
China 1404890000
India 1326093247
logical (AND) — countries with 300M–500M people:
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
FILTER(?population > 300000000 && ?population < 500000000)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
United States 340110988
string (STRSTARTS) — countries whose English label starts with "S":
SELECT ?countryLabel WHERE {
?country wdt:P31 wd:Q6256 .
?country rdfs:label ?countryLabel .
FILTER(LANG(?countryLabel) = "en" && STRSTARTS(?countryLabel, "S"))
}
LIMIT 3
Result:
Saint Kitts and Nevis
Somaliland
Saint Vincent and the Grenadines
numeric (ROUND) — France's population in millions, rounded:
SELECT ?millions (ROUND(?millions) AS ?rounded) WHERE {
wd:Q142 wdt:P1082 ?population .
BIND(?population / 1000000 AS ?millions)
}
Result:
68.605616 69
date/time (YEAR) — Einstein's birth year:
SELECT ?personLabel (YEAR(?birth) AS ?year) WHERE {
wd:Q937 wdt:P569 ?birth .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
Albert Einstein 1879
term test (isIRI) — the values of wdt:P31 on a dog
are entities (IRIs), not literals:
SELECT ?o WHERE {
wd:Q144 wdt:P31 ?o .
FILTER(isIRI(?o))
}
Result:
http://www.wikidata.org/entity/Q55983715
http://www.wikidata.org/entity/Q136772238
Gotcha: an unbound variable in a FILTER makes the row fail (unbound ≠ false) — guard with
BOUND()or restructure with OPTIONAL.
VALUES & BIND
VALUES restricts a variable to a list; BIND computes a new variable. Together: birth years of two people, computed, not looked up:
SELECT ?personLabel ?birthYear WHERE {
VALUES ?person { wd:Q937 wd:Q76 } # Einstein, Obama
?person wdt:P569 ?birth .
BIND(YEAR(?birth) AS ?birthYear)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
Albert Einstein 1879
Barack Obama 1961
Running example: dogs and cats
GROUP BY + COUNT + VALUES — how many of each animal are in Wikidata?
SELECT ?animal ?animalLabel (COUNT(?item) AS ?count) WHERE {
VALUES ?animal { wd:Q144 wd:Q146 } # dog, cat
?item wdt:P31 ?animal . # ?item is an instance of ?animal
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?animal ?animalLabel
Result:
dog 553
cat 239
OPTIONAL, UNION, MINUS
| Keyword | Meaning |
|---|---|
| OPTIONAL | left join: keep the row, leave the variable unbound when absent |
| UNION | alternatives (the default between patterns is AND, not OR) |
| MINUS | remove rows that match the pattern |
OPTIONAL — Einstein (died 1955) vs Obama (alive); ?deathLabel is unbound for Obama:
SELECT ?personLabel ?deathLabel WHERE {
VALUES ?person { wd:Q937 wd:Q76 } # Einstein, Barack Obama
OPTIONAL { ?person wdt:P570 ?death . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
Albert Einstein 1955-04-18
Barack Obama (unbound)
MINUS — Nobel laureates minus the French ones:
SELECT ?personLabel WHERE {
?person wdt:P166 wd:Q7191 .
MINUS { ?person wdt:P27 wd:Q142 . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 3
Result:
Nobel Prize winner
Adam Bernau
Santiago Carril
UNION — dogs AND cats in one result set:
SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE {
{ ?item wdt:P31 wd:Q144 . BIND("dog" AS ?animalLabel) }
UNION
{ ?item wdt:P31 wd:Q146 . BIND("cat" AS ?animalLabel) }
}
GROUP BY ?animalLabel
Result:
dog 553
cat 239
Gotcha: the default between triple patterns is AND (join) — use UNION for alternatives.
Gotcha:
FILTER NOT EXISTSdiffers fromMINUSwhen variables are unbound — prefer MINUS for set-difference semantics.
Property paths
| Path | Meaning |
|---|---|
| wdt:P40/wdt:P40 | two hops (sequence) |
| wdt:P40+ | one or more hops |
| wdt:P40* | zero or more hops |
| wdt:P40? | zero or one hop |
| wdt:P41 | either property |
| ^wdt:P40 | inverse direction |
| !wdt:P40 | any property except P40 |
wdt:P31/wdt:P279* — named dogs, including breeds and other subclasses ("instance of something that is a dog or a subclass of dog"):
SELECT ?thing ?thingLabel WHERE {
?thing wdt:P31/wdt:P279* wd:Q144 .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 3
Result:
Theo
Tich
Tickle Em Jock
Gotcha: variables used only inside a property path (e.g.
?s wdt:P40/wdt:P40 ?o) cannot be selected.
Aggregates
COUNT, SUM, AVG, MIN, MAX, SAMPLE (pick one arbitrary value), GROUP_CONCAT.
HAVING — species with more than 400 direct instances (the running example, filtered):
SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE {
VALUES ?animal { wd:Q144 wd:Q146 }
?item wdt:P31 ?animal .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?animal ?animalLabel
HAVING (COUNT(?item) > 400)
Result:
dog 553
GROUP_CONCAT — Einstein's awards in one cell:
SELECT ?personLabel (GROUP_CONCAT(?awardLabel; SEPARATOR=", ") AS ?awards) WHERE {
VALUES ?person { wd:Q937 }
?person wdt:P166 ?award .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?personLabel
Result:
Albert Einstein Nobel Prize in Physics, …
Gotcha: aggregates need GROUP BY for every non-aggregated variable; forgetting one mixes unrelated rows.
Subqueries
A query inside a query — useful for "the X with the max Y" patterns.
The most populous country, computed via a subquery:
SELECT ?countryLabel ?max WHERE {
{
SELECT (MAX(?population) AS ?max) WHERE {
?c wdt:P31 wd:Q6256 .
?c wdt:P1082 ?population .
}
}
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?max .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Result:
China 1404890000
SERVICE (labels, federation)
The label service turns entity IDs into human-readable labels — used in most queries above:
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
# then reference ?xLabel for every ?x in the query
# Federating to another endpoint (needs the remote's own IRIs, e.g. via owl:sameAs)
SELECT ?cityLabel WHERE {
wd:Q64 wdt:P36 ?city .
?city owl:sameAs ?dbpediaCity .
SERVICE <https://dbpedia.org/sparql> {
?dbpediaCity rdfs:label ?cityLabel .
FILTER(LANG(?cityLabel) = "en")
}
}
Further reading
- Wikidata SPARQL tutorial — the recommended tutorial
- SPARQL 1.1 Query Language — official spec
- Wikidata Query Service — the example endpoint used here
- Help:Contributing/query — querying a different instance (endpoint, prefixes, label service)