SPARQL: querying real-world data¶
The first four chapters used a toy dataset, which is the right way to learn the language. Actual datasets have shapes of their own, and three of them come back so often in Dutch practice that they are worth knowing in advance: hierarchies, geometries and statistics.
Each has a standard model behind it, and each becomes straightforward once you recognise the model. This chapter is a field guide rather than a reference.
It assumes the four chapters before it, and property paths in particular.
Hierarchies¶
Taxonomies, classification schemes, organisational structures and asset breakdowns are all the same shape: things pointing at their parents. Four predicates cover most of what you will meet:
| Predicate | Relates |
|---|---|
rdfs:subClassOf |
A class to a broader class |
rdfs:subPropertyOf |
A property to a broader property |
skos:broader |
A concept to a broader concept |
skos:narrower |
A concept to a narrower concept |
All four are transitive in intent: if A is under B and B is under C, then A is
under C. Whether those indirect links exist as triples depends on whether
anyone inferred them. This is why property paths matter here — skos:broader+
walks the chain whether or not the shortcuts were materialised.
SKOS distinguishes the two explicitly: skos:broader is the direct step, and
skos:broaderTransitive is the closure. Querying with
skos:broaderTransitive*/skos:notation "88" finds everything at or beneath the
concept numbered 88, however deep.
The query that drives most hierarchy visualisations returns pairs — one row per child with its parent:
prefix skos: <http://www.w3.org/2004/02/skos/core#>
select distinct ?childLabel ?parentLabel
where {
?child
skos:broaderTransitive ?parent;
skos:prefLabel ?childLabel.
?parent skos:prefLabel ?parentLabel.
}
A tree, a treemap and a sunburst are all the same two columns drawn differently.
See SKOS for the model itself.
Geometries¶
Geospatial linked data follows GeoSPARQL, and its structure trips people up because there are three levels, not two:
A feature is the thing in the world. A geometry is its shape. A serialisation is that shape written down, in Well-Known Text (WKT) or GML. The split exists because one feature can have several shapes — a 2D footprint and a 3D model — and each shape can be written in more than one format.
So a query for shapes goes through the middle step:
prefix bag: <http://bag.basisregistraties.overheid.nl/def/bag#>
prefix geo: <http://www.opengis.net/ont/geosparql#>
select ?feature ?shape
where {
?feature
a bag:Pand;
geo:hasGeometry ?geometry.
?geometry geo:asWKT ?shape.
}
limit 1
The ?geometry variable is never used in the output, which is precisely the case
for a property path and an anonymous node:
prefix bag: <http://bag.basisregistraties.overheid.nl/def/bag#>
prefix geo: <http://www.opengis.net/ont/geosparql#>
select ?shape
where {
[ a bag:Pand;
geo:hasGeometry/geo:asWKT ?shape ].
}
limit 1
Same query, two fewer moving parts.
A simpler predicate exists for point locations: geo:location carries
coordinates directly, without the geometry step. Use it when a single point is
all you have.
What happens to a WKT literal after it is returned — whether it lands on a map, gets a colour or a height — is a property of the tool displaying it, not of SPARQL. See Data views.
Statistics¶
Statistical data uses the RDF Data Cube vocabulary, which is a linked data expression of the same model behind SDMX. Three concepts carry it:
| Term | What it is |
|---|---|
| Observation | One measured value — the equivalent of a single cell |
| Dimension | What identifies that value: place, year, age group |
| Measure | What was actually measured: life expectancy, population |
An observation states its dimensions and its measure together:
observation:0007ddade4
a qb:Observation;
qb:dataSet dataset:countries;
dimension:location country:Netherlands;
dimension:year "2002"^^xsd:gYear;
measure:lifeExpectancy 7.9696e1.
A fourth piece, the data structure definition, declares which dimensions and measures a dataset uses. Read it first when you meet an unfamiliar cube — it is the table of contents.
Querying a cube is nearly always the same move: fix the dimensions you are not interested in, vary the one you are, and return the measure. Fix the year and vary the country to compare places; fix the country and vary the year to see a trend.
prefix dimension: <...>
prefix measure: <...>
prefix qb: <http://purl.org/linked-data/cube#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?countryName ?value
where {
?observation
a qb:Observation;
dimension:year "2007"^^xsd:gYear;
dimension:location ?country;
measure:lifeExpectancy ?value.
?country rdfs:label ?countryName.
}
That is a chart: one column of labels, one column of numbers.
Where this appears in Triply products¶
- TriplyDB's Insights page builds its class hierarchy from
rdfs:subClassOf, which is the first pattern on this page. See Data views. - These three shapes are the backbone of Triply's public-sector work: cadastral and building data, national statistics, and controlled vocabularies in the cultural heritage sector.
Where to next¶
- SKOS — the model behind the hierarchies on this page
- OWL and ontologies — where
rdfs:subClassOfcomes from - Construct, ask, describe and federation — back one chapter
- SPARQL: the basics — back to the first chapter
- Glossary — every term on this page, in one place