Cheatsheets:SPARQL: Difference between revisions

From Wikibase
Jump to navigation Jump to search
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>.
(works against any Wikibase endpoint). For querying a specific Wikibase
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 !! Example
! Form !! Returns !! Use when
|-
|-
| SELECT || table of variable bindings || <syntaxhighlight lang="sparql" inline>SELECT ?s ?p ?o WHERE { ?s ?p ?o }</syntaxhighlight>
| SELECT || table of variable bindings || you want rows of data (the rest of this sheet)
|-
|-
| ASK || boolean — does the pattern match? || <syntaxhighlight lang="sparql" inline>ASK WHERE { ?s ?p ?o }</syntaxhighlight>
| ASK || true/false || you only need to know whether something exists
|-
|-
| CONSTRUCT || an RDF graph || <syntaxhighlight lang="sparql" inline>CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }</syntaxhighlight>
| CONSTRUCT || an RDF graph (triples) || you want the result as RDF, not a table
|-
|-
| DESCRIBE || a graph describing the resource || <syntaxhighlight lang="sparql" inline>DESCRIBE ?s WHERE { ?s ?p ?o }</syntaxhighlight>
| DESCRIBE || a graph describing the resource || you want everything known about an entity
|}
|}


== Prefixes & triple patterns ==
<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>


Prefixes abbreviate IRIs; the binding is endpoint-defined.
== 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">
PREFIX ex: <http://example.org/>
# What is the population of France? (→ 68,605,616)
SELECT ?s ?p ?o WHERE {
SELECT ?population WHERE {
   ?s ?p ?o .                   # triple pattern: subject predicate object
   wd:Q142 wdt:P1082 ?population .
  FILTER(?p = ex:age)          # constraint on a variable
}
}
# 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>
Anonymous/blank node as subject or object: <syntaxhighlight lang="sparql" inline>[] ex:age 42</syntaxhighlight>.
Literals can carry datatypes or language tags:
<syntaxhighlight lang="sparql" inline>"text"^^xsd:string</syntaxhighlight>,
<syntaxhighlight lang="sparql" inline>"café"@fr</syntaxhighlight>.


== Solution modifiers ==
== Solution modifiers ==


{| class="wikitable"
{| class="wikitable"
! Clause !! Effect
! Clause !! What it does
|-
|-
| DISTINCT || drop duplicate solution rows
| DISTINCT || drop duplicate rows
|-
|-
| ORDER BY || sort: <syntaxhighlight lang="sparql" inline>ORDER BY ASC(?x) DESC(?y)</syntaxhighlight>
| ORDER BY || sort (<syntaxhighlight lang="sparql" inline>ASC(?)</syntaxhighlight> / <syntaxhighlight lang="sparql" inline>DESC(?)</syntaxhighlight>)
|-
|-
| LIMIT n / OFFSET n || page through results
| LIMIT n || at most n rows
|-
|-
| GROUP BY || group rows for aggregation (see below)
| OFFSET n || skip n rows (paging)
|-
|-
| HAVING || filter groups, like WHERE for aggregates
| GROUP BY || group rows for aggregation (see Aggregates)
|}
|}


== FILTER expressions ==
<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 !! Examples
! 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() STRENDS() REGEX()</syntaxhighlight>
| string || <syntaxhighlight lang="sparql" inline>STR() CONTAINS() STRSTARTS() REGEX()</syntaxhighlight>
|-
|-
| numeric || <syntaxhighlight lang="sparql" inline>ABS() ROUND() FLOOR() CEIL() RAND()</syntaxhighlight>
| 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>
|-
|-
| terms || <syntaxhighlight lang="sparql" inline>isIRI() isBlank() isLiteral() LANG() DATATYPE()</syntaxhighlight>
| term tests || <syntaxhighlight lang="sparql" inline>isIRI() isBlank() isLiteral() LANG() DATATYPE()</syntaxhighlight>
|}
|}


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
FILTER(CONTAINS(STR(?label), "cat"))
# Countries with more than 1 billion people (→ China, India)
FILTER(LANG(?label) = "fr")
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 ?p { ex:age ex:name }       # restrict variable to a list
# Restrict ?animal to a fixed list (see the running example)
BIND(?a + ?b AS ?sum)               # compute and bind a new variable
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">
?s ex:name ?n .
# Einstein (died 1955) vs Obama (alive): OPTIONAL leaves ?deathLabel unbound
OPTIONAL { ?s ex:age ?a }           # left join — ?a missing when absent
SELECT ?personLabel ?deathLabel WHERE {
{ ?s ex:age ?a } UNION { ?s ex:name ?n }  # union of two patterns
  VALUES ?person { wd:Q937 wd:Q76 }         # Einstein, Barack Obama
?s ?p ?o .
  OPTIONAL { ?person wdt:P570 ?death . }
MINUS { ?s ex:age 42 }             # remove matches
  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>
Gotcha: <syntaxhighlight lang="sparql" inline>FILTER NOT EXISTS</syntaxhighlight> vs
<syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> differ when a variable is
unbound — prefer <syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> for
set-difference semantics.


== Property paths ==
== Property paths ==
Line 104: Line 181:
! Path !! Meaning
! Path !! Meaning
|-
|-
| <syntaxhighlight lang="sparql" inline>ex:parent/ex:parent</syntaxhighlight> || sequence (length 2)
| <syntaxhighlight lang="sparql" inline>wdt:P40/wdt:P40</syntaxhighlight> || two hops (sequence)
|-
|-
| <syntaxhighlight lang="sparql" inline>ex:parent+</syntaxhighlight> || one or more
| <syntaxhighlight lang="sparql" inline>wdt:P40+</syntaxhighlight> || one or more hops
|-
|-
| <syntaxhighlight lang="sparql" inline>ex:parent*</syntaxhighlight> || zero or more
| <syntaxhighlight lang="sparql" inline>wdt:P40*</syntaxhighlight> || zero or more hops
|-
|-
| <syntaxhighlight lang="sparql" inline>ex:parent?</syntaxhighlight> || zero or one
| <syntaxhighlight lang="sparql" inline>wdt:P40?</syntaxhighlight> || zero or one hop
|-
|-
| <syntaxhighlight lang="sparql" inline>ex:p1|ex:p2</syntaxhighlight> || either property
| <syntaxhighlight lang="sparql" inline>wdt:P40|wdt:P41</syntaxhighlight> || either property
|-
|-
| <syntaxhighlight lang="sparql" inline>^ex:parent</syntaxhighlight> || inverse direction
| <syntaxhighlight lang="sparql" inline>^wdt:P40</syntaxhighlight> || inverse direction
|-
|-
| <syntaxhighlight lang="sparql" inline>!ex:p1</syntaxhighlight> || any property except p1
| <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 ?p (COUNT(?s) AS ?n) (SUM(?x) AS ?total) (SAMPLE(?o) AS ?any)
# Species with more than 400 direct instances (the running example with HAVING)
WHERE { ?s ?p ?o . ?s ex:val ?x }
SELECT ?animalLabel (COUNT(?item) AS ?n) WHERE {
GROUP BY ?p
  VALUES ?animal { wd:Q144 wd:Q146 }
HAVING (COUNT(?s) > 2)
  ?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>


Other aggregates: <syntaxhighlight lang="sparql" inline>AVG() MIN() MAX()</syntaxhighlight>,
== Subqueries ==
<syntaxhighlight lang="sparql" inline>GROUP_CONCAT(?o; SEPARATOR=", ")</syntaxhighlight>.


== Subqueries ==
A query inside a query — useful for "the X with the max Y" patterns.


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
SELECT ?s WHERE {
# The most populous country, computed via a subquery (→ China)
   { SELECT ?s (MAX(?v) AS ?maxv) WHERE { ?s ex:val ?v } GROUP BY ?s }
SELECT ?countryLabel ?max WHERE {
   ?s ex:val ?maxv
   {
    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>


== Federated queries (SERVICE) ==
== 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 ?label WHERE {
# Federating to another endpoint (needs the remote's own IRIs, e.g. via owl:sameAs)
   ?s ex:ref ?w .
SELECT ?cityLabel WHERE {
   SERVICE <https://www.wikidata.org/sparql> {
   wd:Q64 wdt:P36 ?city .
     ?w rdfs:label ?label . FILTER(LANG(?label) = "en")
  ?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 { ?s ?p ?o }</syntaxhighlight>
* '''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 direction''': <syntaxhighlight lang="sparql" inline>?child ^ex:parent ?parent</syntaxhighlight>
* '''Reverse a relation''': <syntaxhighlight lang="sparql" inline>?child ^wdt:P40 ?parent</syntaxhighlight>
* '''Check existence''': <syntaxhighlight lang="sparql" inline>ASK</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)''', not OR — use UNION for alternatives.
* 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 (filter is not "true" for unbound) — guard with <syntaxhighlight lang="sparql" inline>BOUND()</syntaxhighlight> or use OPTIONAL.
* 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 ex:p1/ex:p2 ?o</syntaxhighlight>) cannot be selected.
* 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 (e.g. <syntaxhighlight lang="sparql" inline>_:x</syntaxhighlight>) are local to one query — they are not IRIs.
* Blank-node labels (<syntaxhighlight lang="sparql" inline>_:x</syntaxhighlight>) are local to one query — they are not IRIs.
* Aggregates require GROUP BY for non-aggregated variables; forgetting it mixes unrelated rows.
* Aggregates need GROUP BY for every non-aggregated variable; forgetting one mixes unrelated rows.
* <syntaxhighlight lang="sparql" inline>LIMIT 0</syntaxhighlight> returns no rows but still validates the query.
* <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 specific instance (endpoint, prefixes, label service)
* [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

Languages: English · français · Esperanto

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

  • 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
# 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=json to the endpoint URL

Gotchas

  • The default between triple patterns is AND (join) — use UNION for alternatives.
  • An unbound variable in FILTER makes the row fail (unbound ≠ false) — guard with BOUND() 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
    
    ≠
    MINUS
    
    when variables are unbound — prefer MINUS for set-difference semantics.
  • Endpoint prefixes are not universal — wd:/wdt: are Wikidata's; other instances define their own (see Help:Contributing/query).

Further reading