Using SPARQL & the data.gov.uk school data
- February 10th, 2010
- Posted in Development . Local Government . Technology . Tutorials
- Write comment
So i’ve been busy beavering away on the myDistrict project I’m developing for Stratford-on-Avon District Council, and part of this project is to retrieve various datasets from numerous API’s to enable the Stratford residents to get all their local information in one place.
The basics are there, and we’ll be gathering the residents geo information when they register (or upgrade their existing website account) so we are able to query all these fantastic datasets from www.data.gov.uk and more.
A bit stuck at first, I asked the Open Data guru from Lichfield District Council, Stuart Harrison, for some pointers. Stuart was very kind as to email through some sample code and links to blogs which reference the calls needed to access and unleash the data.
I thought I’d share some of this with you all, do with it what you will!
A few sample snippets are below, but you’ll need to replace some parts (especially the local authority district reference eg 44UE) with your own data to get accurate results.
You can find your ‘id’ number by having a look through the data.gov.uk lists here. This is the Warwickshire County starting point, you’ll need to go up a level to country and search that way. It’s a bit fiddly! Once you’re in the right county, you’ll need to look for local authority district. If I find a better way, I’ll update this post!
UPDATE: Stuart Harrison has kindly written a nice service to allow you to search for your council ID (or SNAC ID for the technical amongst you).
So, starting on the UK Government SPARQL form input page, you can start to play with the various options to tailor your results accordingly.
To call back all the schools in your local authority (in this case, Stratford):
prefix sch-ont: <http://education.data.gov.uk/def/school/>
SELECT ?name ?reference WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:uniqueReferenceNumber ?reference ;
sch-ont:districtAdministrative<http://statistics.data.gov.uk/id/local-authority-district/44UE> .
}
ORDER BY ?name
To filter by primary school you can add an extra couple of lines:
prefix sch-ont: <http://education.data.gov.uk/def/school/>
SELECT ?name ?reference WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:uniqueReferenceNumber ?reference ;
sch-ont:districtAdministrative<http://statistics.data.gov.uk/id/local-authority-district/44UE> ;
sch-ont:uniqueReferenceNumber ?reference ; sch-ont:phaseOfEducation <http://education.data.gov.uk/def/school/PhaseOfEducation_Primary> .
}
ORDER BY ?name
And to filter just secondary schools, you can make a small change also:
prefix sch-ont: <http://education.data.gov.uk/def/school/>
SELECT ?name ?reference WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:uniqueReferenceNumber ?reference ;
sch-ont:districtAdministrative<http://statistics.data.gov.uk/id/local-authority-district/44UE> ;
sch-ont:uniqueReferenceNumber ?reference ; sch-ont:phaseOfEducation <http://education.data.gov.uk/def/school/PhaseOfEducation_Secondary> .
}
ORDER BY ?name
You could also pull back which schools have nurseries attached, very handy!
prefix sch-ont: <http://education.data.gov.uk/def/school/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>SELECT ?name WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:districtAdministrative <http://statistics.data.gov.uk/id/local-authority-district/44UE> ;sch-ont:nurseryProvision “true”^^xsd:boolean ;
}
ORDER BY ?name
Or you could pull back all the nursery schools available across the whole county. Just by tweaking a couple of search parameters:
prefix sch-ont: <http://education.data.gov.uk/def/school/>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>SELECT ?name WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:localAuthority <http://statistics.data.gov.uk/id/local-education-authority/937> ;sch-ont:nurseryProvision “true”^^xsd:boolean ;
}
ORDER BY ?name
And then, if you want to get really flash, you can return the 5 closest primary schools to your location. In this example, using easting & northing data and adding address data to the mix as well:
prefix sch-ont: <http://education.data.gov.uk/def/school/>
prefix space: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/>SELECT ?name ?address1 ?address2 ?town ?postcode ?easting ?northing ?reference ?WebsiteAddress ?SCUpreferredemail
WHERE { ?school a sch-ont:School ; sch-ont:districtAdministrative
<http://statistics.data.gov.uk/id/local-authority-district/44UE> ;
sch-ont:establishmentName ?name;
sch-ont:uniqueReferenceNumber ?reference ;
space:easting ?easting ;
space:northing ?northing ;sch-ont:uniqueReferenceNumber ?reference ; sch-ont:phaseOfEducation
<http://education.data.gov.uk/def/school/PhaseOfEducation_Primary> .
OPTIONAL {
?school sch-ont:address ?address .
?address sch-ont:address1 ?address1 ;
sch-ont:address2 ?address2 ;
sch-ont:town ?town ;
sch-ont:postcode ?postcode .}
OPTIONAL {
?school sch-ont:WebsiteAddress ?WebsiteAddress ;}
OPTIONAL {
?school sch-ont:SCUpreferredemail ?SCUpreferredemail ;
}
}
ORDER BY ASC(
((419997 – ?easting)* ( 419997 – ?easting))
+ ((254702 – ?northing)* ( 254702 – ?northing)))
LIMIT 5
OFFSET 0
And this one, using longitude and latitude data:
prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>prefix sch-ont: <http://education.data.gov.uk/def/school/>SELECT ?name ?address1 ?address2 ?town ?postcode ?lat ?long ?reference ?WebsiteAddress ?SCUpreferredemailWHERE {?school a sch-ont:School;sch-ont:establishmentName ?name;sch-ont:districtAdministrative<http://statistics.data.gov.uk/id/local-authority-district/44UE> ;sch-ont:phaseOfEducation <http://education.data.gov.uk/def/school/PhaseOfEducation_Primary>;sch-ont:uniqueReferenceNumber ?reference ;geo:lat ?lat;geo:long ?long.OPTIONAL {?school sch-ont:address ?address .?address sch-ont:address1 ?address1 ;sch-ont:address2 ?address2 ;sch-ont:town ?town ;sch-ont:postcode ?postcode .}OPTIONAL {?school sch-ont:WebsiteAddress ?WebsiteAddress ;}OPTIONAL {?school sch-ont:SCUpreferredemail ?SCUpreferredemail ;}}ORDER BY ASC(((52.190200973202 – ?lat)* ( 52.190200973202 – ?lat))+ ((-1.7088976710252 – ?long)* ( -1.7088976710252 – ?long)))LIMIT 5OFFSET 0
This is really just touching the surface, I’ve got oodles of examples, far too many to post here.
If you have any questions, feel free to email me and I can help out where possible!






Hey Simon,
Looks like you’ve grasped it, it’s awesomely powerful stuff, if a bit fiddly to start with!
As for looking up SNAC IDs for your council, I’ve knocked this quick table up which shows the SNAC ID for all local authorities, using this query on the Office of National Statistics SPARQL endpoint:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?authority ?label
WHERE {
?authority
a <http://statistics.data.gov.uk/def/administrative-geography/LocalAuthority> .
?authority rdfs:label ?label ;
}
ORDER BY ?label
Thanks man, I’ve updated the post to include your service. Thanks again for all the pointers, much appreciated!
“I’ve got oodles of examples, far too many to post here.”
Please share them – the more googleable examples (and this post contains some great ones) that there are for folk to discover, the more chance that we’ll start to see folk having a bit of a play with the SPARQLable datastores.
TIA
tony