Cheatsheets:SPARQL: Difference between revisions

From Wikibase
Jump to navigation Jump to search
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)
Fix rendering defects: intro link newline, stray quote in inline tags, raw <> inside syntaxhighlight (via update-page on MediaWiki MCP Server)
Line 3: Line 3:
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. For a proper tutorial, take the
[https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL
[https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial Wikidata SPARQL tutorial]
tutorial] (works against any Wikibase endpoint). For querying *this* instance
(works against any Wikibase endpoint). For querying a specific Wikibase
(endpoint, prefixes, label service), see [[Help:Contributing/query]].
instance (endpoint, prefixes, label service), see [[Help:Contributing/query]].


== Query forms ==
== Query forms ==
Line 59: Line 59:
! Category !! Examples
! Category !! Examples
|-
|-
| comparison || <syntaxhighlight lang="sparql" inline>= &lt; &gt; &lt;= &gt;= !=</syntaxhighlight>
| comparison || <syntaxhighlight lang="sparql" inline>= < > <= >= !=</syntaxhighlight>
|-
|-
| logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight>
| logical || <syntaxhighlight lang="sparql" inline>&& || !</syntaxhighlight>
Line 95: Line 95:


Gotcha: <syntaxhighlight lang="sparql" inline>FILTER NOT EXISTS</syntaxhighlight> vs
Gotcha: <syntaxhighlight lang="sparql" inline>FILTER NOT EXISTS</syntaxhighlight> vs
<syntaxhighlight lang="sparql" inline">MINUS</syntaxhighlight> differ when a variable is
<syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> differ when a variable is
unbound — prefer <syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> for
unbound — prefer <syntaxhighlight lang="sparql" inline>MINUS</syntaxhighlight> for
set-difference semantics.
set-difference semantics.
Line 125: Line 125:
WHERE { ?s ?p ?o . ?s ex:val ?x }
WHERE { ?s ?p ?o . ?s ex:val ?x }
GROUP BY ?p
GROUP BY ?p
HAVING (COUNT(?s) &gt; 2)
HAVING (COUNT(?s) > 2)
</syntaxhighlight>
</syntaxhighlight>


Line 162: Line 162:


* The default is '''AND (join)''', not OR — use UNION for alternatives.
* The default is '''AND (join)''', not OR — 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 (filter is not "true" for unbound) — guard with <syntaxhighlight lang="sparql" inline>BOUND()</syntaxhighlight> or use 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 ex:p1/ex:p2 ?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 (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.
* 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.
* <syntaxhighlight lang="sparql" inline>LIMIT 0</syntaxhighlight> returns no rows but still validates the query.


== Further reading ==
== Further reading ==
Line 172: Line 172:
* [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 this instance (endpoint, prefixes, label service)
* [[Help:Contributing/query]] — querying a specific instance (endpoint, prefixes, label service)

Revision as of 11:20, 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 Wikidata SPARQL tutorial (works against any Wikibase endpoint). For querying a specific Wikibase 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 = < > <= >= !=
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) > 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