Learning.md: Notes from the SPARQL youtube series by Wouter Beek

SPARQL

Notes I made while watching Wouter Beek’s series on SparQL. It should be noted

Terms

Syntax:

  • ?variable
  • <absolute-uri>
  • end of a tripple pattern.
  • repeat the subject;
  • repeat the subject and predicate,

?s ?p ?o –> subject/predicate/object


Notation Example
Absolute IRI <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>
Relative IRI <type> (requires base)
Prefixed IRI rdf:type (requires prefix)
Type IRI a (only in predicate position)

(Table imported from this video)


Symbol Notation type
. Simple triple
; Predicate list
, Object list

(Table imported from this video)


Example Datatype IRI
false xsd:boolean
11 xsd:integer
1.1 xsd:decimal
1.1e0 xsd:double
“abc” xsd:string

prefix xsd: <http://www.w3.org/2001/XMLSchema#>

(Table imported from here)


  • Okay so one thing you have to understand is that you can’t look at sparql like most code where it goes line-by-line. The entire thing gets parsed at once
  • Don’t interpet it as an SQL database. Just because a Record has a property called Track, doesn’t mean you can query for Tracks.
  • Also it’s case sensitive! mo:Record & mo:track work. mo:record & mo:Track breaks. (Usually, a capital means it’s a type, and a non-capital means it’s a predicate)
  • There are somewhat-standardised prefixes. See the Linked Open Vocabularies vocabs page (for some/all of them?)

Structure

Note: you can test out the triplydb/pokemon examples here

Okay, the value you provide and where you put ?variables changes things

1
2
3
WHERE {
?thing rdf:type ?type .
}

Queries everything with rdf:type for example

Basic spo select

1
2
3
4
5
6
# Prologue

SELECT ?s ?p ?o { # Projection: columns
?s ?p ?o. # Pattern: cells/content
}
limit x # Modifier: affects rows

Filter select on object value

  • ?p can be replaced with a predicate uri: ?p –> https://triplydb.com/academy/pokemon/vocab/colour
  • ?o can be replaced with a specific object: ?0 –> “yellow”
    1
    2
    3
    select ?pokemon {
    ?pokemon <https://triplydb.com/academy/pokemon/vocab/colour> "yellow"
    }

Bind (assigning variables)

1
2
3
4
5
select ?pokemon ?color ? greeting {
?pokemon <https://triplydb.com/academy/pokemon/vocab/colour> ?color.
bind("Hi!" as ?greeting)
}
limit 10

Literal string interpretation

1
2
3
4
select ?location {
# "literal"^^<how-to-interpet>
bind("Point(4.8649 52.33287)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> as ?location)
}

Bind calculation

1
2
3
4
select ?pokemon ?weightKilograms ?weightPounds {
?pokemon <https://triplidb.com/academy/pokemon/vocab/weight> ?weightKilograms.
bind(?weightKilograms * "2.20462"^^<http://www.w3.org/2001/XMLSchema#float> as ?weightPounds)
}

Query against multiple of the same, only returning when there are multiple but allowing switching around/duplicate

1
2
3
4
5
6
7
select ?color ?cry ?name ?type1 ?type2 {
?pokemon <https://triplydb.com/academy/pokemon/vocab/colour> ?color.
?pokemon <https://triplydb.com/academy/pokemon/vocab/cry> ?cry.
?pokemon <http://www.w3.org/2000/01/rdf-schema#label> ?name.
?pokemon <https://triplydb.com/academy/pokemon/vocab/type> ?type1.
?pokemon <https://triplydb.com/academy/pokemon/vocab/type> ?type2.
}

Get an object from an object of an object

1
2
3
4
5
6
7
8
9
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon <https://triplydb.com/academy/pokemon/vocab/colour> ?color.
?pokemon <https://triplydb.com/academy/pokemon/vocab/cry> ?cry.
?pokemon <http://www.w3.org/2000/01/rdf-schema#label> ?name.
?pokemon <https://triplydb.com/academy/pokemon/vocab/type> ?type1.
?pokemon <https://triplydb.com/academy/pokemon/vocab/type> ?type2.
?type1 <http://www.w3.org/2000/01/rdf-schema#label> ?type1Name.
?type2 <http://www.w3.org/2000/01/rdf-schema#label> ?type2Name.
}

Abbrevations

Use prefixes to shorten the previous query

Most prefixes end with / or #

1
2
3
4
5
6
7
8
9
10
11
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix vocab: <https://triplydb.com/academy/pokemon/vocab/>
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon vocab:colour ?color.
?pokemon vocab:cry ?cry.
?pokemon rdfs:label ?name.
?pokemon vocab:type ?type1.
?pokemon vocab:type ?type2.
?type1 rdfs:label ?type1Name.
?type2 rdfs:label ?type2Name.
}

Use base IRI

1
2
3
4
5
6
7
8
9
10
11
base <https://triplydb.com/academy/pokemon/vocab/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon <colour> ?color.
?pokemon <cry> ?cry.
?pokemon rdfs:label ?name.
?pokemon <type> ?type1.
?pokemon <type> ?type2.
?type1 rdfs:label ?type1Name.
?type2 rdfs:label ?type2Name.
}

Empty alias

1
2
3
4
5
6
7
8
9
10
11
base <https://triplydb.com/academy/pokemon/vocab/>
prefix : <http://www.w3.org/2000/01/rdf-schema#>
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon <colour> ?color.
?pokemon <cry> ?cry.
?pokemon :label ?name.
?pokemon <type> ?type1.
?pokemon <type> ?type2.
?type1 :label ?type1Name.
?type2 :label ?type2Name.
}

Special IRI: rdf type

<http://www.3.org/1999/02/22-rdf-syntax-ns#type> -> a
(This can only be used in the predicate position, not object or subject)

1
2
3
4
5
6
7
8
9
10
11
12
base <https://triplydb.com/academy/pokemon/vocab/>
prefix : <http://www.w3.org/2000/01/rdf-schema#>
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon a ?class.
?pokemon <colour> ?color.
?pokemon <cry> ?cry.
?pokemon :label ?name.
?pokemon <type> ?type1.
?pokemon <type> ?type2.
?type1 :label ?type1Name.
?type2 :label ?type2Name.
}

In literals

1
2
3
4
prefix geo: <http://www.opengis.net/ont/geosparql#>
select ?location {
bind("Point(4.8649 52.33287)"^^geo:wktLiteral as ?location)
}

End-of-lines

1
2
3
4
5
6
7
8
9
10
11
12
base <https://triplydb.com/academy/pokemon/vocab/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?color ?cry ?name ?type1Name ?type2Name {
?pokemon a ?class;
<colour> ?color;
<cry> ?cry;
rdfs:label ?name;
<type> ?type1, # You could also type <type> ?type1, ?type2 on one line
?type2.

?type1 rdfs:label ?type1Name, ?type2Name.
}

Literal abbrevations (see table above)

1
2
3
4
5
6
prefix vocab: <https://triplydb.com/academy/pokemon/vocab/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?pokemon {
# ?pokemon vocab:weight "80"^^xsd:integer.
?pokemon vocab:weight 80.
}

Bind + functions + html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
prefix vocab: <https://triplydb.com/academy/pokemon/vocab/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?color ?name ?text ?widget {
?pokemon
vocab:colour ?color;
vocab:cry ?cry;
rdfs:label ?name;
foaf:depiction ?image.
bind(concat("Hi!", " ", ?name) as ?text)

# bind(concat("202", "0")^^xsd:gYear as ?widget) # --> Error
# bind(strdt(concat("202", "0"), xsd:gYear) as ?widget) # --> No error

bind(strdt(concat("<h2 style='color:", ?color, "'>", ?name, "</h2><img src='", str(?image), "'><audio controls><source src='", str(?cry), "'></audio>"), rdf:HTML) as ?widget)
}
limit 10

Discover all available predicates

1
2
3
4
prefix mo: <http://purl.org/ontology/mo/>
SELECT DISTINCT ?p {
?record a mo:Record; ?p ?o.
}

(Thanks Felix!)

Also check out Sparklis & its examples! (Thanks Claire!)

Thanks to Wouter Beeks video series as well as my colleagues for not banning me from the rocket chat for my questions


Here’s some other queries I made that don’t fit in the above because they work but I barely understand them myself but they might contain wisdom somewhere

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix mo: <http://purl.org/ontology/mo/>
prefix dc: <http://purl.org/dc/elements/1.1/>


SELECT ?title (SUM(?duration)/1000/60 AS ?total_duration_in_min) {
?record a mo:Record;
dc:title ?title;
mo:track ?track.
?track mo:duration ?duration.
}
GROUP BY ?title
HAVING((SUM(?duration)/(1000.0*60.0)) < 60)
ORDER BY DESC(?total_duration_in_min)
LIMIT 10

(Thanks Claire, Riad and Niels for dealing with my spam about this)