Cheatsheets:SPARQL: Difference between revisions

From Wikibase
Jump to navigation Jump to search
Fix examples: use P1 (instance of) not P31 (subclass of); real class values Q2/Q3 (via update-page on MediaWiki MCP Server)
Rewrite as generic SPARQL 1.1 syntax cheatsheet (not a tutorial, not instance-coupled); point to Wikidata tutorial + instance guide (via update-page on MediaWiki MCP Server)
Line 1: Line 1:
{{Cheatsheet}}
{{Cheatsheet}}


Cheatsheet for querying this instance's data with SPARQL against the
SPARQL 1.1 quick syntax reference — for people who already know what SPARQL is
Wikibase Query Service.
and need reminders on syntax. For a proper tutorial, take the
[https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL
tutorial] (works against any Wikibase endpoint). For querying *this* instance
(endpoint, prefixes, label service), see [[Help:Contributing/query]].


== Quick start ==
== Query forms ==


The endpoint is <syntaxhighlight lang="text" inline>https://wikibase.ronzz.org/sparql</syntaxhighlight>.
{| class="wikitable"
A minimal query (returns one column of entity URIs):
! Form !! Returns !! Example
|-
| SELECT || table of variable bindings || <syntaxhighlight lang="sparql" inline>SELECT ?s ?p ?o WHERE { ?s ?p ?o }</syntaxhighlight>
|-
| ASK || boolean — does the pattern match? || <syntaxhighlight lang="sparql" inline>ASK WHERE { ?s ?p ?o }</syntaxhighlight>
|-
| CONSTRUCT || an RDF graph || <syntaxhighlight lang="sparql" inline>CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }</syntaxhighlight>
|-
| DESCRIBE || a graph describing the resource || <syntaxhighlight lang="sparql" inline>DESCRIBE ?s WHERE { ?s ?p ?o }</syntaxhighlight>
|}
 
== Prefixes & triple patterns ==
 
Prefixes abbreviate IRIs; the binding is endpoint-defined.


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
PREFIX wd: <https://wikibase.ronzz.org/entity/>
PREFIX ex: <http://example.org/>
PREFIX wdt: <https://wikibase.ronzz.org/prop/direct/>
SELECT ?s ?p ?o WHERE {
SELECT ?item WHERE { ?item wdt:P1 wd:Q2 . } LIMIT 10
  ?s ?p ?o .                    # triple pattern: subject predicate object
  FILTER(?p = ex:age)          # constraint on a variable
}
</syntaxhighlight>
</syntaxhighlight>


== Query structure ==
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 ==


{| class="wikitable"
{| class="wikitable"
! Part !! Role
! Clause !! Effect
|-
|-
| PREFIX || Namespace shorthand; '''must''' be declared (see gotchas)
| DISTINCT || drop duplicate solution rows
|-
|-
| SELECT || Variables to return
| ORDER BY || sort: <syntaxhighlight lang="sparql" inline>ORDER BY ASC(?x) DESC(?y)</syntaxhighlight>
|-
|-
| WHERE || Triple patterns in curly braces
| LIMIT n / OFFSET n || page through results
|-
|-
| FILTER / VALUES / BIND || Constraints and computed values
| GROUP BY || group rows for aggregation (see below)
|-
|-
| LIMIT / OFFSET || Paging (nginx enforces a 300 s cap, see gotchas)
| HAVING || filter groups, like WHERE for aggregates
|}
|}


== Instance prefixes ==
== FILTER expressions ==


{| class="wikitable"
{| class="wikitable"
! Prefix !! Expands to !! Use for
! Category !! Examples
|-
|-
| wd: || https://wikibase.ronzz.org/entity/ || Items (Q…) and properties (P…) as subjects/values
| comparison || <syntaxhighlight lang="sparql" inline>= &lt; &gt; &lt;= &gt;= !=</syntaxhighlight>
|-
|-
| wdt: || https://wikibase.ronzz.org/prop/direct/ || Direct property statements (P…)
| logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight>
|-
|-
| wikibase: || built-in || The label service, etc.
| string || <syntaxhighlight lang="sparql" inline>STR() CONTAINS() STRSTARTS() STRENDS() REGEX()</syntaxhighlight>
|-
| numeric || <syntaxhighlight lang="sparql" inline>ABS() ROUND() FLOOR() CEIL() RAND()</syntaxhighlight>
|-
| date/time || <syntaxhighlight lang="sparql" inline>YEAR() MONTH() DAY() NOW()</syntaxhighlight>
|-
| terms || <syntaxhighlight lang="sparql" inline>isIRI() isBlank() isLiteral() LANG() DATATYPE()</syntaxhighlight>
|}
|}


== Basic patterns ==
<syntaxhighlight lang="sparql">
FILTER(CONTAINS(STR(?label), "cat"))
FILTER(LANG(?label) = "fr")
</syntaxhighlight>
 
== VALUES & BIND ==
 
<syntaxhighlight lang="sparql">
VALUES ?p { ex:age ex:name }        # restrict variable to a list
BIND(?a + ?b AS ?sum)              # compute and bind a new variable
</syntaxhighlight>
 
== OPTIONAL, UNION, MINUS ==


* '''instance of''' is '''P1''' — this instance does not mirror Wikidata's P31
<syntaxhighlight lang="sparql">
* '''Q1''' is the "Spike test item" — useful for testing, but it carries no claims
?s ex:name ?n .
* Seed classes, all instance-of P1: '''Q2''' quotation content, '''Q3''' code snippet, '''Q4''' mathematical expression, '''Q5''' programming language
OPTIONAL { ?s ex:age ?a }          # left join — ?a missing when absent
* Typical pattern: <syntaxhighlight lang="sparql" inline>?item wdt:P1 wd:Q2 .</syntaxhighlight>
{ ?s ex:age ?a } UNION { ?s ex:name ?n }  # union of two patterns
?s ?p ?o .
MINUS { ?s ex:age 42 }              # remove matches
</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 ==
 
{| class="wikitable"
! Path !! Meaning
|-
| <syntaxhighlight lang="sparql" inline>ex:parent/ex:parent</syntaxhighlight> || sequence (length 2)
|-
| <syntaxhighlight lang="sparql" inline>ex:parent+</syntaxhighlight> || one or more
|-
| <syntaxhighlight lang="sparql" inline>ex:parent*</syntaxhighlight> || zero or more
|-
| <syntaxhighlight lang="sparql" inline>ex:parent?</syntaxhighlight> || zero or one
|-
| <syntaxhighlight lang="sparql" inline>ex:p1|ex:p2</syntaxhighlight> || either property
|-
| <syntaxhighlight lang="sparql" inline>^ex:parent</syntaxhighlight> || inverse direction
|-
| <syntaxhighlight lang="sparql" inline>!ex:p1</syntaxhighlight> || any property except p1
|}


== FILTER, VALUES, BIND ==
== Aggregates ==


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
PREFIX wd: <https://wikibase.ronzz.org/entity/>
SELECT ?p (COUNT(?s) AS ?n) (SUM(?x) AS ?total) (SAMPLE(?o) AS ?any)
PREFIX wdt: <https://wikibase.ronzz.org/prop/direct/>
WHERE { ?s ?p ?o . ?s ex:val ?x }
SELECT ?item ?name WHERE {
GROUP BY ?p
  VALUES ?type { wd:Q2 wd:Q3 }
HAVING (COUNT(?s) &gt; 2)
  ?item wdt:P1 ?type .
  BIND(STR(?item) AS ?name)
  FILTER(CONTAINS(?name, "Q"))
}
LIMIT 10
</syntaxhighlight>
</syntaxhighlight>


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


Labels are not in the graph — use <syntaxhighlight lang="sparql" inline>wikibase:label</syntaxhighlight>:
== Subqueries ==


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
PREFIX wd: <https://wikibase.ronzz.org/entity/>
SELECT ?s WHERE {
PREFIX wdt: <https://wikibase.ronzz.org/prop/direct/>
  { SELECT ?s (MAX(?v) AS ?maxv) WHERE { ?s ex:val ?v } GROUP BY ?s }
SELECT ?item ?itemLabel ?typeLabel WHERE {
   ?s ex:val ?maxv
  ?item wdt:P1 ?type .
   SERVICE wikibase:label { bd:serviceParam wikibase:language "en,fr,eo". }
}
}
LIMIT 10
</syntaxhighlight>
</syntaxhighlight>


The instance's official languages are '''en, fr, eo''' — list them in this order.
== Federated queries (SERVICE) ==
 
== Aggregation ==


<syntaxhighlight lang="sparql">
<syntaxhighlight lang="sparql">
PREFIX wd: <https://wikibase.ronzz.org/entity/>
SELECT ?label WHERE {
PREFIX wdt: <https://wikibase.ronzz.org/prop/direct/>
  ?s ex:ref ?w .
SELECT ?type (COUNT(?item) AS ?n) WHERE {
  SERVICE <https://www.wikidata.org/sparql> {
   ?item wdt:P1 ?type .
    ?w rdfs:label ?label . FILTER(LANG(?label) = "en")
   }
}
}
GROUP BY ?type
ORDER BY DESC(?n)
LIMIT 10
</syntaxhighlight>
</syntaxhighlight>


== Common tasks ==
== Common tasks ==


* '''Count triples''': <syntaxhighlight lang="sparql" inline>SELECT (COUNT(?s) AS ?n) WHERE { ?s ?p ?o }</syntaxhighlight>
* '''Count rows''': <syntaxhighlight lang="sparql" inline>SELECT (COUNT(*) AS ?n) WHERE { ?s ?p ?o }</syntaxhighlight>
* '''Deduplicate''': add <syntaxhighlight lang="sparql" inline>DISTINCT</syntaxhighlight>
* '''Reverse direction''': <syntaxhighlight lang="sparql" inline>?child ^ex:parent ?parent</syntaxhighlight>
* '''Check existence''': <syntaxhighlight lang="sparql" inline>ASK</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
* '''Test a fresh entity''': query it via <syntaxhighlight lang="text" inline>?item wdt:P1 ?type</syntaxhighlight> first, then build up


== Gotchas ==
== Gotchas ==


* '''The default wd:/wdt: prefixes resolve to wikidata.org, not this instance''' — always declare them explicitly, or queries silently return 0 results.
* The default is '''AND (join)''', not OR — use UNION for alternatives.
* '''nginx caps SPARQL requests at 300 s''' — keep queries small, page with LIMIT/OFFSET.
* 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.
* '''The WDQS updater can lag behind the wiki''' (known fresh-instance catch-up quirk) — a just-created entity may not appear in SPARQL immediately; re-check later.
* Variables used only inside a property path (e.g. <syntaxhighlight lang="sparql" inline">?s ex:p1/ex:p2 ?o</syntaxhighlight>) cannot be selected.
* '''No Wikidata P-number mirroring''' — property IDs here (P1, P2, …) are local; use equivalence statements instead of assuming Wikidata numbers.
* Blank-node labels (e.g. <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.
* <syntaxhighlight lang="sparql" inline">LIMIT 0</syntaxhighlight> returns no rows but still validates the query.


== Further reading ==
== Further reading ==


* [[Help:Contributing/query]] — querying with SPARQL on this instance
* [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] — works verbatim against any Wikibase
* [https://www.w3.org/TR/sparql11-query/ SPARQL 1.1 Query Language] — official spec
* [https://www.w3.org/TR/sparql11-query/ SPARQL 1.1 spec]
* [[Help:Contributing/query]] — querying this instance (endpoint, prefixes, label service)

Revision as of 11:18, 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. For a proper tutorial, take the [https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial] (works against any Wikibase endpoint). For querying *this* instance (endpoint, prefixes, label service), see Help:Contributing/query.

Query forms

Form Returns Example
SELECT table of variable bindings SELECT ?s ?p ?o WHERE { ?s ?p ?o }
ASK boolean — does the pattern match? ASK WHERE { ?s ?p ?o }
CONSTRUCT an RDF graph CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }
DESCRIBE a graph describing the resource DESCRIBE ?s WHERE { ?s ?p ?o }

Prefixes & triple patterns

Prefixes abbreviate IRIs; the binding is endpoint-defined.

PREFIX ex: <http://example.org/>
SELECT ?s ?p ?o WHERE {
  ?s ?p ?o .                    # triple pattern: subject predicate object
  FILTER(?p = ex:age)           # constraint on a variable
}

Anonymous/blank node as subject or object: [] ex:age 42. Literals can carry datatypes or language tags: "text"^^xsd:string, "café"@fr.

Solution modifiers

Clause Effect
DISTINCT drop duplicate solution rows
ORDER BY sort: ORDER BY ASC(?x) DESC(?y)
LIMIT n / OFFSET n page through results
GROUP BY group rows for aggregation (see below)
HAVING filter groups, like WHERE for aggregates

FILTER expressions

Category Examples
comparison = &lt; &gt; &lt;= &gt;= !=
logical && || !
string STR() CONTAINS() STRSTARTS() STRENDS() REGEX()
numeric ABS() ROUND() FLOOR() CEIL() RAND()
date/time YEAR() MONTH() DAY() NOW()
terms isIRI() isBlank() isLiteral() LANG() DATATYPE()
FILTER(CONTAINS(STR(?label), "cat"))
FILTER(LANG(?label) = "fr")

VALUES & BIND

VALUES ?p { ex:age ex:name }        # restrict variable to a list
BIND(?a + ?b AS ?sum)               # compute and bind a new variable

OPTIONAL, UNION, MINUS

?s ex:name ?n .
OPTIONAL { ?s ex:age ?a }           # left join — ?a missing when absent
{ ?s ex:age ?a } UNION { ?s ex:name ?n }   # union of two patterns
?s ?p ?o .
MINUS { ?s ex:age 42 }              # remove matches

Gotcha: FILTER NOT EXISTS vs

MINUS

differ when a variable is

unbound — prefer MINUS for set-difference semantics.

Property paths

Path Meaning
ex:parent/ex:parent sequence (length 2)
ex:parent+ one or more
ex:parent* zero or more
ex:parent? zero or one
ex:p1|ex:p2 either property
^ex:parent inverse direction
!ex:p1 any property except p1

Aggregates

SELECT ?p (COUNT(?s) AS ?n) (SUM(?x) AS ?total) (SAMPLE(?o) AS ?any)
WHERE { ?s ?p ?o . ?s ex:val ?x }
GROUP BY ?p
HAVING (COUNT(?s) &gt; 2)

Other aggregates: AVG() MIN() MAX(), GROUP_CONCAT(?o; SEPARATOR=", ").

Subqueries

SELECT ?s WHERE {
  { SELECT ?s (MAX(?v) AS ?maxv) WHERE { ?s ex:val ?v } GROUP BY ?s }
  ?s ex:val ?maxv
}

Federated queries (SERVICE)

SELECT ?label WHERE {
  ?s ex:ref ?w .
  SERVICE <https://www.wikidata.org/sparql> {
    ?w rdfs:label ?label . FILTER(LANG(?label) = "en")
  }
}

Common tasks

  • Count rows: SELECT (COUNT(*) AS ?n) WHERE { ?s ?p ?o }
  • Deduplicate: add DISTINCT
  • Reverse direction: ?child ^ex:parent ?parent
  • Check existence: ASK
  • JSON output: append &format=json to the endpoint URL

Gotchas

  • The default is AND (join), not OR — use UNION for alternatives.
  • An unbound variable in
    FILTER
    
    makes the row fail (filter is not "true" for unbound) — guard with
    BOUND()
    
    or use OPTIONAL.
  • Variables used only inside a property path (e.g.
    ?s ex:p1/ex:p2 ?o
    
    ) cannot be selected.
  • Blank-node labels (e.g.
    _:x
    
    ) are local to one query — they are not IRIs.
  • Aggregates require GROUP BY for non-aggregated variables; forgetting it mixes unrelated rows.
  • LIMIT 0
    
    returns no rows but still validates the query.

Further reading