PREFIX prefix: <IRI> # declare prefix (can have multiple)BASE <IRI> # base IRI for relative referencesSELECT ... # variables to returnFROM <graph> # data graph (default graph)FROM NAMED <graph> # named graphWHERE { ... } # graph patternsGROUP BY ... # groupingHAVING (...) # group filterORDER BY ... # sortingLIMIT n # max resultsOFFSET n # skip results
Prologue Declarations
# PREFIX - multiple allowed, creates shortcutsPREFIX i: <http://db.cz/terms#>PREFIX m: <http://db.cz/movies/>PREFIX : <http://default.org/> # empty prefix# BASE - at most one, for relative IRIsBASE <http://db.cz/># Usagei:Movie # expands to <http://db.cz/terms#Movie>m:samotari # expands to <http://db.cz/movies/samotari>:something # expands to <http://default.org/something>
Variables
?variable # standard variable syntax$variable # alternative syntax (equivalent)# Both are identical:SELECT ?name ?ageSELECT $name $age
Triple Patterns
Basic Triples
# Full form - separated by .?m rdf:type i:Movie .?m i:title ?t .?m i:year ?y .# Predicate-object list with ; (same subject)?m rdf:type i:Movie ; i:title ?t ; i:year ?y .# Object list with , (same subject and predicate)?m i:actor a:trojan , a:machacek .# Equivalent to:?m i:actor a:trojan .?m i:actor a:machacek .
# Query specific named graphFROM <http://db.cz/movies>FROM NAMED <http://db.cz/actors>WHERE { m:medvidek i:actor ?a . # from default graph GRAPH <http://db.cz/actors> { # from named graph ?a i:firstname ?f ; i:lastname ?l . }}# Query all named graphsWHERE { GRAPH ?g { ?s ?p ?o } # ?g binds to graph IRI}
BIND
# Assign computed value to new variableWHERE { ?a i:firstname ?f ; i:lastname ?l . BIND ( CONCAT(?f, " ", ?l) AS ?fullname )}# Variable must not already be bound!
IN (value1, value2, ...)NOT IN (value1, value2, ...)FILTER ( ?day IN ("MON", "FRI") )FILTER ( ?status NOT IN ("deleted", "archived") )
String Functions
REGEX(?string, "pattern") # regex matchREGEX(?string, "pattern", "i") # case-insensitiveFILTER ( REGEX(?code, "^NPRG") ) # starts with NPRGFILTER ( REGEX(?name, "son$", "i") ) # ends with son (case-insensitive)STR(?term) # lexical form of IRI or literalSTRLEN(?str) # string lengthSUBSTR(?str, start, length) # substring (1-indexed)UCASE(?str) # uppercaseLCASE(?str) # lowercaseCONTAINS(?str, "sub") # contains substringSTRSTARTS(?str, "prefix") # starts withSTRENDS(?str, "suffix") # ends withCONCAT(?str1, " ", ?str2) # concatenationREPLACE(?str, "old", "new") # replace
Type/Term Tests
BOUND(?var) # true if variable is bound!BOUND(?var) # true if variable is NOT boundisIRI(?term) # true if IRIisBLANK(?term) # true if blank nodeisLITERAL(?term) # true if literalLANG(?literal) # language tagDATATYPE(?literal) # datatype IRI
Existence Tests
EXISTS { pattern } # true if pattern matches at least onceNOT EXISTS { pattern } # true if pattern doesn't matchFILTER EXISTS { ?m i:actor a:trojan }FILTER NOT EXISTS { ?m i:director ?d }
COALESCE(expr1, expr2, ...) # first non-error valueBIND ( COALESCE(?nickname, ?firstname, "Unknown") AS ?displayName )
SELECT Clause
# Select specific variablesSELECT ?title ?year# Select all variablesSELECT *# Computed expressions with aliasSELECT ?title (?year + 1 AS ?nextYear)SELECT (CONCAT(?first, " ", ?last) AS ?fullName)# AggregatesSELECT ?director (COUNT(?m) AS ?movieCount)# Remove duplicatesSELECT DISTINCT ?actor# May remove some duplicates (implementation-dependent)SELECT REDUCED ?actor
FROM Clause
# Default graph (merged if multiple)FROM <http://db.cz/movies>FROM <http://db.cz/actors> # merged into default graph# Named graphs (for GRAPH pattern)FROM NAMED <http://db.cz/movies>FROM NAMED <http://db.cz/actors># CombinedFROM <http://db.cz/movies>FROM NAMED <http://db.cz/actors>
Solution Modifiers
ORDER BY
ORDER BY ?year # ascending (default)ORDER BY ASC(?year) # ascending (explicit)ORDER BY DESC(?year) # descending# Multiple criteriaORDER BY DESC(?year) ASC(?title)# By expressionORDER BY STRLEN(?title)
LIMIT and OFFSET
LIMIT 10 # return at most 10 resultsOFFSET 5 # skip first 5 results# PaginationORDER BY ?idLIMIT 10OFFSET 20 # page 3 (results 21-30)
Aggregation
GROUP BY
# Group by one or more variablesSELECT ?director (COUNT(?m) AS ?count)WHERE { ?m i:director ?director }GROUP BY ?director# Must include all non-aggregated SELECT variablesSELECT ?director ?year (COUNT(?m) AS ?count)WHERE { ?m i:director ?director ; i:year ?year }GROUP BY ?director ?year# Group by expressionGROUP BY (YEAR(?date) AS ?year)
HAVING
# Filter groups (like WHERE but for aggregated results)SELECT ?director (COUNT(?m) AS ?count)WHERE { ?m i:director ?director }GROUP BY ?directorHAVING (COUNT(?m) >= 3)SELECT ?s ?f ?l (AVG(?r) AS ?avg)WHERE { ... }GROUP BY ?s ?f ?lHAVING (COUNT(?c) <= 10)
# Average study results for students with at most 10 courses# Ignore enrollments with undefined results# Describe students by full namesPREFIX i: <http://nosql.opendata.cz/school/terms#>PREFIX s: <http://nosql.opendata.cz/school/>SELECT ?f ?l (AVG(?r) AS ?avg)FROM <http://nosql.opendata.cz/school/pdb-251/>WHERE { ?s rdf:type i:Student ; i:name [ i:first ?f ; i:last ?l ] ; i:enroll [ i:course ?c ; i:result ?r ; i:semester s:semester251 ] .}GROUP BY ?s ?f ?lHAVING (COUNT(?c) <= 10)