Cheatsheets:SPARQL
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 | = < > <= >= !=
|
| 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=jsonto the endpoint URL
Gotchas
- The default is AND (join), not OR — use UNION for alternatives.
- An unbound variable in makes the row fail (filter is not "true" for unbound) — guard with
FILTERor use OPTIONAL.BOUND()
- Variables used only inside a property path (e.g. ) cannot be selected.
?s ex:p1/ex:p2 ?o
- Blank-node labels (e.g. ) are local to one query — they are not IRIs.
_:x - Aggregates require GROUP BY for non-aggregated variables; forgetting it mixes unrelated rows.
- returns no rows but still validates the query.
LIMIT 0
Further reading
- Wikidata SPARQL tutorial — the recommended tutorial
- SPARQL 1.1 Query Language — official spec
- Help:Contributing/query — querying this instance (endpoint, prefixes, label service)