Cheatsheets:SPARQL: Difference between revisions
Fix rendering defects: intro link newline, stray quote in inline tags, raw <> inside syntaxhighlight (via update-page on MediaWiki MCP Server) |
Show, don't tell: real verified Wikidata queries for every construct (dogs/cats, populations, Nobel laureates, Einstein vs Obama) (via update-page on MediaWiki MCP Server) |
||
| Line 2: | Line 2: | ||
SPARQL 1.1 quick syntax reference — for people who already know what SPARQL is | SPARQL 1.1 quick syntax reference — for people who already know what SPARQL is | ||
and need reminders on syntax. For a proper tutorial, take the | and need reminders on syntax. All examples run as-is against the public | ||
[https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial] | Wikidata endpoint <syntaxhighlight lang="text" inline>https://query.wikidata.org/sparql</syntaxhighlight>. | ||
For a proper tutorial, take the | |||
instance (endpoint, prefixes, label service), see [[Help:Contributing/query]]. | [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]]. | |||
== Running example == | |||
How many dogs and cats are in Wikidata? (returns: dog 553, cat 239) | |||
<syntaxhighlight lang="sparql"> | |||
# wd: = entity (Q…), wdt: = property value (P…), SERVICE = label lookup | |||
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 || | |||
| dog || 553 | |||
|- | |||
| cat || 239 | |||
== Query forms == | == Query forms == | ||
{| class="wikitable" | {| class="wikitable" | ||
! Form !! Returns !! | ! Form !! Returns !! Use when | ||
|- | |- | ||
| SELECT || table of variable bindings || | | SELECT || table of variable bindings || you want rows of data (the rest of this sheet) | ||
|- | |- | ||
| ASK || | | ASK || true/false || you only need to know whether something exists | ||
|- | |- | ||
| CONSTRUCT || an RDF graph || | | CONSTRUCT || an RDF graph (triples) || you want the result as RDF, not a table | ||
|- | |- | ||
| DESCRIBE || a graph describing the resource || | | DESCRIBE || a graph describing the resource || you want everything known about an entity | ||
|} | |} | ||
= | <syntaxhighlight lang="sparql"> | ||
# Is there at least one dog in Wikidata? | |||
ASK WHERE { ?x wdt:P31 wd:Q144 . } # → true | |||
# Every dog as an RDF graph (first two) | |||
CONSTRUCT { ?x wdt:P31 wd:Q144 . } | |||
WHERE { ?x wdt:P31 wd:Q144 . } LIMIT 2 | |||
</syntaxhighlight> | |||
== Triple patterns & literals == | |||
A triple pattern is <syntaxhighlight lang="sparql" inline>subject predicate object .</syntaxhighlight> — | |||
each part may be a variable (<syntaxhighlight lang="sparql" inline>?x</syntaxhighlight>), an IRI | |||
(<syntaxhighlight lang="sparql" inline">wd:Q144</syntaxhighlight>), or a literal. | |||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
# What is the population of France? (→ 68,605,616) | |||
SELECT ? | SELECT ?population WHERE { | ||
? | wd:Q142 wdt:P1082 ?population . | ||
} | } | ||
# Literals can carry datatypes or language tags: | |||
# "42"^^xsd:integer "2026-08-19"^^xsd:date | |||
# "dog"@en "chien"@fr | |||
# A blank node means "some unnamed thing": | |||
# wd:Q144 wdt:depicted-by [] . # dog depicted by something | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== Solution modifiers == | == Solution modifiers == | ||
{| class="wikitable" | {| class="wikitable" | ||
! Clause !! | ! Clause !! What it does | ||
|- | |- | ||
| DISTINCT || drop duplicate | | DISTINCT || drop duplicate rows | ||
|- | |- | ||
| ORDER BY || sort | | ORDER BY || sort (<syntaxhighlight lang="sparql" inline>ASC(?)</syntaxhighlight> / <syntaxhighlight lang="sparql" inline>DESC(?)</syntaxhighlight>) | ||
|- | |- | ||
| LIMIT | | LIMIT n || at most n rows | ||
|- | |- | ||
| | | OFFSET n || skip n rows (paging) | ||
|- | |- | ||
| | | GROUP BY || group rows for aggregation (see Aggregates) | ||
|} | |} | ||
== FILTER | <syntaxhighlight lang="sparql"> | ||
# The 3 most populous countries (ORDER BY + LIMIT) | |||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . # instance of: sovereign state | |||
?country wdt:P1082 ?population . | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
ORDER BY DESC(?population) | |||
LIMIT 3 | |||
</syntaxhighlight> | |||
Result: China 1,404,890,000 · India 1,326,093,247 · United States 340,110,988 | |||
== FILTER == | |||
{| class="wikitable" | {| class="wikitable" | ||
! Category !! | ! Category !! Operators / functions | ||
|- | |- | ||
| comparison || <syntaxhighlight lang="sparql" inline>= < > <= >= !=</syntaxhighlight> | | comparison || <syntaxhighlight lang="sparql" inline>= < > <= >= !=</syntaxhighlight> | ||
| Line 63: | Line 108: | ||
| logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight> | | logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight> | ||
|- | |- | ||
| string || <syntaxhighlight lang="sparql" inline>STR() CONTAINS() STRSTARTS | | string || <syntaxhighlight lang="sparql" inline>STR() CONTAINS() STRSTARTS() REGEX()</syntaxhighlight> | ||
|- | |- | ||
| numeric || <syntaxhighlight lang="sparql" inline>ABS() ROUND() FLOOR() CEIL | | numeric || <syntaxhighlight lang="sparql" inline>ABS() ROUND() FLOOR() CEIL()</syntaxhighlight> | ||
|- | |- | ||
| date/time || <syntaxhighlight lang="sparql" inline>YEAR() MONTH() DAY() NOW()</syntaxhighlight> | | date/time || <syntaxhighlight lang="sparql" inline>YEAR() MONTH() DAY() NOW()</syntaxhighlight> | ||
|- | |- | ||
| | | term tests || <syntaxhighlight lang="sparql" inline>isIRI() isBlank() isLiteral() LANG() DATATYPE()</syntaxhighlight> | ||
|} | |} | ||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
FILTER | # Countries with more than 1 billion people (→ China, India) | ||
SELECT ?countryLabel ?population WHERE { | |||
?country wdt:P31 wd:Q6256 . | |||
?country wdt:P1082 ?population . | |||
FILTER(?population > 1000000000) | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
# France's population in millions (FILTER + BIND arithmetic) | |||
SELECT ?population ?millions WHERE { | |||
wd:Q142 wdt:P1082 ?population . | |||
BIND(?population / 1000000 AS ?millions) | |||
} # → 68.605616 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 80: | Line 136: | ||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
VALUES ? | # Restrict ?animal to a fixed list (see the running example) | ||
BIND(? | VALUES ?animal { wd:Q144 wd:Q146 } | ||
# Compute a new variable from existing ones | |||
BIND(?population / 1000000 AS ?millions) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== OPTIONAL, UNION, MINUS == | == OPTIONAL, UNION, MINUS == | ||
* <syntaxhighlight lang="sparql" inline">OPTIONAL</syntaxhighlight> — left join: keep the row, leave the variable unbound when absent | |||
* <syntaxhighlight lang="sparql" inline">UNION</syntaxhighlight> — alternatives (the default between patterns is AND, not OR) | |||
* <syntaxhighlight lang="sparql" inline">MINUS</syntaxhighlight> — remove rows that match the pattern | |||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
# Einstein (died 1955) vs Obama (alive): OPTIONAL leaves ?deathLabel unbound | |||
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". } | |||
} | |||
# → Albert Einstein 1955-04-18 | |||
# → Barack Obama (no death row) | |||
# Nobel laureates minus the French ones (MINUS) | |||
SELECT ?personLabel WHERE { | |||
?person wdt:P166 wd:Q7191 . | |||
MINUS { ?person wdt:P27 wd:Q142 . } | |||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } | |||
} | |||
LIMIT 3 | |||
# Dogs AND cats in one result set (UNION + DISTINCT + GROUP BY) | |||
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> | </syntaxhighlight> | ||
== Property paths == | == Property paths == | ||
| Line 104: | Line 181: | ||
! Path !! Meaning | ! Path !! Meaning | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline> | | <syntaxhighlight lang="sparql" inline>wdt:P40/wdt:P40</syntaxhighlight> || two hops (sequence) | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline> | | <syntaxhighlight lang="sparql" inline>wdt:P40+</syntaxhighlight> || one or more hops | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline> | | <syntaxhighlight lang="sparql" inline>wdt:P40*</syntaxhighlight> || zero or more hops | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline> | | <syntaxhighlight lang="sparql" inline>wdt:P40?</syntaxhighlight> || zero or one hop | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline> | | <syntaxhighlight lang="sparql" inline>wdt:P40|wdt:P41</syntaxhighlight> || either property | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline>^ | | <syntaxhighlight lang="sparql" inline>^wdt:P40</syntaxhighlight> || inverse direction | ||
|- | |- | ||
| <syntaxhighlight lang="sparql" inline>! | | <syntaxhighlight lang="sparql" inline>!wdt:P40</syntaxhighlight> || any property except P40 | ||
|} | |} | ||
<syntaxhighlight lang="sparql"> | |||
# Named dogs, including breeds and other subclasses of dog | |||
# (wdt:P31/wdt:P279* = "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 | |||
</syntaxhighlight> | |||
Result: Theo · Tich · Tickle Em Jock | |||
== Aggregates == | == Aggregates == | ||
COUNT, SUM, AVG, MIN, MAX, SAMPLE (pick one arbitrary value), GROUP_CONCAT. | |||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
SELECT ? | # Species with more than 400 direct instances (the running example with HAVING) | ||
WHERE { ? | SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE { | ||
GROUP BY ? | 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) # → only dog: 553 | |||
# Collect labels into 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 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== Subqueries == | |||
A query inside a query — useful for "the X with the max Y" patterns. | |||
<syntaxhighlight lang="sparql"> | <syntaxhighlight lang="sparql"> | ||
SELECT ? | # The most populous country, computed via a subquery (→ China) | ||
{ SELECT | 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> | </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"> | <syntaxhighlight lang="sparql"> | ||
SELECT ? | # Federating to another endpoint (needs the remote's own IRIs, e.g. via owl:sameAs) | ||
? | SELECT ?cityLabel WHERE { | ||
SERVICE <https:// | wd:Q64 wdt:P36 ?city . | ||
? | ?city owl:sameAs ?dbpediaCity . | ||
SERVICE <https://dbpedia.org/sparql> { | |||
?dbpediaCity rdfs:label ?cityLabel . | |||
FILTER(LANG(?cityLabel) = "en") | |||
} | } | ||
} | } | ||
| Line 153: | Line 274: | ||
== Common tasks == | == Common tasks == | ||
* '''Count rows''': <syntaxhighlight lang="sparql" inline>SELECT (COUNT(*) AS ?n) WHERE { | * '''Count rows''': <syntaxhighlight lang="sparql" inline>SELECT (COUNT(*) AS ?n) WHERE { … }</syntaxhighlight> | ||
* '''Check existence''': <syntaxhighlight lang="sparql" inline>ASK WHERE { … }</syntaxhighlight> | |||
* '''Deduplicate''': add <syntaxhighlight lang="sparql" inline>DISTINCT</syntaxhighlight> | * '''Deduplicate''': add <syntaxhighlight lang="sparql" inline>DISTINCT</syntaxhighlight> | ||
* '''Reverse | * '''Reverse a relation''': <syntaxhighlight lang="sparql" inline>?child ^wdt:P40 ?parent</syntaxhighlight> | ||
* ''' | * '''Page through results''': <syntaxhighlight lang="sparql" inline>LIMIT 100 OFFSET 100</syntaxhighlight> | ||
* '''JSON output''': append <syntaxhighlight lang="text" inline>&format=json</syntaxhighlight> to the endpoint URL | * '''JSON output''': append <syntaxhighlight lang="text" inline>&format=json</syntaxhighlight> to the endpoint URL | ||
== Gotchas == | == Gotchas == | ||
* The default is '''AND (join)''' | * The default between triple patterns is '''AND (join)''' — use UNION for alternatives. | ||
* An unbound variable in <syntaxhighlight lang="sparql" inline>FILTER</syntaxhighlight> makes the row fail ( | * An unbound variable in <syntaxhighlight lang="sparql" inline>FILTER</syntaxhighlight> makes the row fail (unbound ≠ false) — guard with <syntaxhighlight lang="sparql" inline>BOUND()</syntaxhighlight> or restructure with OPTIONAL. | ||
* Variables used only inside a property path (e.g. <syntaxhighlight lang="sparql" inline>?s | * Variables used only inside a property path (e.g. <syntaxhighlight lang="sparql" inline>?s wdt:P40/wdt:P40 ?o</syntaxhighlight>) cannot be selected. | ||
* Blank-node labels ( | * Blank-node labels (<syntaxhighlight lang="sparql" inline>_:x</syntaxhighlight>) are local to one query — they are not IRIs. | ||
* Aggregates | * Aggregates need GROUP BY for every non-aggregated variable; forgetting one mixes unrelated rows. | ||
* <syntaxhighlight lang="sparql" inline> | * <syntaxhighlight lang="sparql" inline">FILTER NOT EXISTS</syntaxhighlight> ≠ <syntaxhighlight lang="sparql" inline">MINUS</syntaxhighlight> when variables are unbound — prefer MINUS for set-difference semantics. | ||
* Endpoint prefixes are not universal — <syntaxhighlight lang="sparql" inline>wd:</syntaxhighlight>/<syntaxhighlight lang="sparql" inline>wdt:</syntaxhighlight> are Wikidata's; other instances define their own (see [[Help:Contributing/query]]). | |||
== Further reading == | == Further reading == | ||
| Line 172: | Line 295: | ||
* [https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial] — the recommended tutorial | * [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://www.w3.org/TR/sparql11-query/ SPARQL 1.1 Query Language] — official spec | ||
* [[Help:Contributing/query]] — querying a | * [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 11:31, 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.
Running example
How many dogs and cats are in Wikidata? (returns: dog 553, cat 239)
# wd: = entity (Q…), wdt: = property value (P…), SERVICE = label lookup
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
Query forms
| Form | Returns | Use when |
|---|---|---|
| SELECT | table of variable bindings | you want rows of data (the rest of this sheet) |
| 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 |
# Is there at least one dog in Wikidata?
ASK WHERE { ?x wdt:P31 wd:Q144 . } # → true
# Every dog as an RDF graph (first two)
CONSTRUCT { ?x wdt:P31 wd:Q144 . }
WHERE { ?x wdt:P31 wd:Q144 . } LIMIT 2
Triple patterns & literals
A triple pattern is subject predicate object . —
each part may be a variable (?x), an IRI
(
wd:Q144
), or a literal.
# What is the population of France? (→ 68,605,616)
SELECT ?population WHERE {
wd:Q142 wdt:P1082 ?population .
}
# Literals can carry datatypes or language tags:
# "42"^^xsd:integer "2026-08-19"^^xsd:date
# "dog"@en "chien"@fr
# A blank node means "some unnamed thing":
# wd:Q144 wdt:depicted-by [] . # dog depicted by something
Solution modifiers
| Clause | What it does |
|---|---|
| DISTINCT | drop duplicate rows |
| ORDER BY | sort (ASC(?) / DESC(?))
|
| LIMIT n | at most n rows |
| OFFSET n | skip n rows (paging) |
| GROUP BY | group rows for aggregation (see Aggregates) |
# The 3 most populous countries (ORDER BY + LIMIT)
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 . # instance of: sovereign state
?country wdt:P1082 ?population .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 3
Result: China 1,404,890,000 · India 1,326,093,247 · United States 340,110,988
FILTER
| Category | Operators / functions |
|---|---|
| comparison | = < > <= >= !=
|
| logical | && || !
|
| string | STR() CONTAINS() STRSTARTS() REGEX()
|
| numeric | ABS() ROUND() FLOOR() CEIL()
|
| date/time | YEAR() MONTH() DAY() NOW()
|
| term tests | isIRI() isBlank() isLiteral() LANG() DATATYPE()
|
# Countries with more than 1 billion people (→ China, India)
SELECT ?countryLabel ?population WHERE {
?country wdt:P31 wd:Q6256 .
?country wdt:P1082 ?population .
FILTER(?population > 1000000000)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
# France's population in millions (FILTER + BIND arithmetic)
SELECT ?population ?millions WHERE {
wd:Q142 wdt:P1082 ?population .
BIND(?population / 1000000 AS ?millions)
} # → 68.605616
VALUES & BIND
# Restrict ?animal to a fixed list (see the running example)
VALUES ?animal { wd:Q144 wd:Q146 }
# Compute a new variable from existing ones
BIND(?population / 1000000 AS ?millions)
OPTIONAL, UNION, MINUS
- — left join: keep the row, leave the variable unbound when absent
OPTIONAL - — alternatives (the default between patterns is AND, not OR)
UNION - — remove rows that match the pattern
MINUS
# Einstein (died 1955) vs Obama (alive): OPTIONAL leaves ?deathLabel unbound
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". }
}
# → Albert Einstein 1955-04-18
# → Barack Obama (no death row)
# Nobel laureates minus the French ones (MINUS)
SELECT ?personLabel WHERE {
?person wdt:P166 wd:Q7191 .
MINUS { ?person wdt:P27 wd:Q142 . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 3
# Dogs AND cats in one result set (UNION + DISTINCT + GROUP BY)
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
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:P40|wdt:P41 |
either property |
^wdt:P40 |
inverse direction |
!wdt:P40 |
any property except P40 |
# Named dogs, including breeds and other subclasses of dog
# (wdt:P31/wdt:P279* = "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
Aggregates
COUNT, SUM, AVG, MIN, MAX, SAMPLE (pick one arbitrary value), GROUP_CONCAT.
# Species with more than 400 direct instances (the running example with HAVING)
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) # → only dog: 553
# Collect labels into 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
Subqueries
A query inside a query — useful for "the X with the max Y" patterns.
# The most populous country, computed via a subquery (→ China)
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". }
}
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")
}
}
Common tasks
- Count rows:
SELECT (COUNT(*) AS ?n) WHERE { … } - Check existence:
ASK WHERE { … } - Deduplicate: add
DISTINCT - Reverse a relation:
?child ^wdt:P40 ?parent - Page through results:
LIMIT 100 OFFSET 100 - JSON output: append
&format=jsonto the endpoint URL
Gotchas
- The default between triple patterns is AND (join) — use UNION for alternatives.
- An unbound variable in
FILTERmakes the row fail (unbound ≠ false) — guard withBOUND()or restructure with OPTIONAL. - Variables used only inside a property path (e.g.
?s wdt:P40/wdt:P40 ?o) cannot be selected. - Blank-node labels (
_:x) are local to one query — they are not IRIs. - Aggregates need GROUP BY for every non-aggregated variable; forgetting one mixes unrelated rows.
- ≠
FILTER NOT EXISTS
when variables are unbound — prefer MINUS for set-difference semantics.MINUS - Endpoint prefixes are not universal —
wd:/wdt:are Wikidata's; other instances define their own (see Help:Contributing/query).
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)