SPARQL


Winter 2019
Instructor: Raghava Mutharaju
IIIT-Delhi
IIIT Delhi

Introduction

SPARQL 1.1 Query Language


  • RDF is a directed, labelled graph
  • SPARQL is a graph pattern language
  • It supports aggregation, subqueries, negation, filters etc.
  • It is similar to SQL in terms of syntax
  • Result of a SPARQL query can be a RDF graph or a result set

Basic Graph Patterns


  • A basic graph pattern (BGP) is a triple pattern
  • A triple pattern is nothing but a triple except that each of the subject, predicate, and object can be a variable
  • A BGP matches a subgraph of a RDF graph when the RDF terms (IRIs, literals, blank nodes) from that subgraph can be substituted for the variables in the BGP

SELECT clause


  • It is a projection
  • It returns variables and their bindings
  • New variable bindings can be introduced in the query

Example

Data


<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> "SPARQL Tutorial" . 

Query

SELECT ?title
WHERE
{
  <http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title .
}

Result

title
SPARQL Tutorial

Data


@prefix foaf:  <http://xmlns.com/foaf/0.1/> .

_:a  foaf:name   "Johnny Lee Outlaw" .
_:a  foaf:mbox   <mailto:jlow@example.com> .
_:b  foaf:name   "Peter Goodguy" .
_:b  foaf:mbox   <mailto:peter@example.org> .
_:c  foaf:mbox   <mailto:carol@example.org> .

Query

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE
  { ?x foaf:name ?name .
    ?x foaf:mbox ?mbox }

Result

name mbox
"Johnny Lee Outlaw" <mailto:jlow@example.com>
"Peter Goodguy" <mailto:peter@example.org>

Data

@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix :     <http://example.org/book/> .
@prefix ns:   <http://example.org/ns#> .

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book1  ns:discount 0.2 .

:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .
:book2  ns:discount 0.25 .

Query

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title (?p*(1-?discount) AS ?price)
{ ?x ns:price ?p .
  ?x dc:title ?title . 
  ?x ns:discount ?discount 
}

Result

title price
"The Semantic Web" 17.25
"SPARQL Tutorial" 33.6

CONSTRUCT


  • This query form returns a RDF graph that matches a graph template
  • This is different from SELECT query form that returns variable bindings
  • If the graph template contains no variables (ground or explicit triples) then the CONSTRUCT query includes them in the result

Example

Data

@prefix org:    <http://example.com/ns#> .

_:a  org:employeeName   "Alice" .
_:a  org:employeeId     12345 .

_:b  org:employeeName   "Bob" .
_:b  org:employeeId     67890 .

Query

PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
PREFIX org:    <http://example.com/ns#>

CONSTRUCT { ?x foaf:name ?name }
WHERE  { ?x org:employeeName ?name }

Result

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
      
_:x foaf:name "Alice" .
_:y foaf:name "Bob" .

Data

@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .

_:a    foaf:name   "Alice" .
_:a    foaf:mbox   <mailto:alice@example.org> .

Query

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>
CONSTRUCT   { <http://example.org/person#Alice> vcard:FN ?name }
WHERE       { ?x foaf:name ?name }

Result

@prefix vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> .

<http://example.org/person#Alice> vcard:FN "Alice" .

FILTER


  • FILTER is used to constrain the RDF terms
  • A FILTER expression can result in either true, false, or error
  • Solutions that result in false or error are eliminated from the result

Example

Data

@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix :     <http://example.org/book/> .
@prefix ns:   <http://example.org/ns#> .

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

Query

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
SELECT  ?title
WHERE   { ?x dc:title ?title
          FILTER regex(?title, "^SPARQL") 
        }

Result

title
"SPARQL Tutorial"

Query

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
SELECT  ?title
WHERE   { ?x dc:title ?title
          FILTER regex(?title, "web", "i" ) 
        }

Result

title
"The Semantic Web"

OPTIONAL


  • Generally, all the basic graph patterns in the query should match a subgraph in order to get a solution
  • But sometimes, it is useful to get a solution even though some part of the query pattern does not match
  • OPTIONAL feature provides this functionality
  • If the optional part does not match, it creates no bindings but does not eliminate the solution

Example

Data

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

_:a  rdf:type        foaf:Person .
_:a  foaf:name       "Alice" .
_:a  foaf:mbox       <mailto:alice@example.com> .
_:a  foaf:mbox       <mailto:alice@work.example> .

_:b  rdf:type        foaf:Person .
_:b  foaf:name       "Bob" .

Query

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE  { ?x foaf:name  ?name .
         OPTIONAL { ?x  foaf:mbox  ?mbox }
       }

Result

name mbox
"Alice" <mailto:alice@example.com>
"Alice" <mailto:alice@work.example>
"Bob"

Data

@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix :     <http://example.org/book/> .
@prefix ns:   <http://example.org/ns#> .

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

Query

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>
SELECT  ?title ?price
WHERE   { ?x dc:title ?title .
          OPTIONAL { ?x ns:price ?price . FILTER (?price < 30) }
        }

Result

title price
"SPARQL Tutorial"
"The Semantic Web" 23

Data

@prefix foaf:       <http://xmlns.com/foaf/0.1/> .

_:a  foaf:name       "Alice" .
_:a  foaf:homepage   <http://work.example.org/alice/> .

_:b  foaf:name       "Bob" .
_:b  foaf:mbox       <mailto:bob@work.example> .

Query

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox ?hpage
WHERE  { ?x foaf:name  ?name .
         OPTIONAL { ?x foaf:mbox ?mbox } .
         OPTIONAL { ?x foaf:homepage ?hpage }
       }

Result


name mbox hpage
"Alice" <http://work.example.org/alice/>
"Bob" <mailto:bob@work.example>

Aggregates


  • Aggregates apply expressions over groups of solutions
  • GROUP BY is used for grouping
  • SPARQL 1.1 supports COUNT, SUM, MIN, MAX, AVG, GROUP_CONCAT, and SAMPLE aggregates

Example

Data

@prefix : <http://books.example/> .

:org1 :affiliates :auth1, :auth2 .
:auth1 :writesBook :book1, :book2 .
:book1 :price 9 .
:book2 :price 5 .
:auth2 :writesBook :book3 .
:book3 :price 7 .
:org2 :affiliates :auth3 .
:auth3 :writesBook :book4 .
:book4 :price 7 .

Query

PREFIX : <http://books.example/>
SELECT ?org (SUM(?lprice) AS ?totalPrice)
WHERE {
  ?org :affiliates ?auth .
  ?auth :writesBook ?book .
  ?book :price ?lprice .
}
GROUP BY ?org
HAVING (SUM(?lprice) > 10)

Result

org totalPrice
org1 21

Data

@prefix : <http://org.example/> .

:org1 :affiliates :p1, :p2, :p6 .
:org2 :affiliates :p3, :p4 .

:p1 :name "John" .
:p2 :name "Paul" .
:p6 :name "John" .
:p3 :name "Ringo" .
:p4 :name "George" .

Query

PREFIX : <http://books.example/>
SELECT ?org (GROUP_CONCAT(DISTINCT ?name;separator=', ') as ?names)
WHERE {?org :affiliates ?p. ?p :name ?name }
GROUP BY ?org

Result

org names
org1 "John, Paul"
org2 "Ringo, George"

Property Paths


  • A property path is a possible route through a graph between two graph nodes
  • A basic graph pattern has a property path length of 1
  • The ends of the path can be RDF terms or variables
  • Paths (properties) cannot be variables. Only the path ends can be variables
  • Property paths allow connectivity match of two resources of arbitrary path length

Example

  • Alternatives: Match one or both possibilities
{ :book1 dc:title|rdfs:label ?displayString }

  • Sequence: Find the name of any people that Alice knows
{
    ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows/foaf:name ?name .
}
  • Sequence: Find the names of people two "foaf:knows" links away
{ 
    ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows/foaf:knows/foaf:name ?name .
}

This is the same as the SPARQL query:

SELECT ?x ?name
{
    ?x  foaf:mbox <mailto:alice@example> .
    ?x  foaf:knows ?a1 .
    ?a1 foaf:knows ?a2 .
    ?a2 foaf:name ?name .
}
  • Filtering duplicates: someone Alice knows may well know Alice
{ ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows/foaf:knows ?y .
    FILTER ( ?x != ?y )
    ?y foaf:name ?name 
}
  • Inverse Property Paths: following two queries are the same.
  • Second query is just reversing the property direction which swaps the roles of subject and object
{ ?x foaf:mbox <mailto:alice@example> }
{ <mailto:alice@example> ^foaf:mbox ?x }
  • Inverse Path Sequence: Find all the people who know someone ?x knows
{
    ?x foaf:knows/^foaf:knows ?y .  
    FILTER(?x != ?y)
}

This is the same as the SPARQL query:

{
    ?x foaf:knows ?a .
    ?y foaf:knows ?a .  
    FILTER(?x != ?y)
}
  • Arbitrary length match: Find the names of all the people that can be reached from Alice by foaf:knows
{
    ?x foaf:mbox <mailto:alice@example> .
    ?x foaf:knows+/foaf:name ?name .
}
  • Alternatives in an arbitrary length path
{ ?ancestor (ex:motherOf|ex:fatherOf)+ <#me> }
  • Inference: some form of limited inference is possible using property paths
  • All resources and all their inferred types
{ ?x rdf:type/rdfs:subClassOf* ?type }
  • Subproperty inference
{ ?x ?p ?v . ?p rdfs:subPropertyOf* :property }
  • Negated Property Paths: Find nodes connected but not by rdf:type (either way round)
{ ?x !(rdf:type|^rdf:type) ?y }
  • Find all the elements in an RDF collection
{ :list rdf:rest*/rdf:first ?element }

SPARQL Query Forms


  • There are four different SPARQL query forms
    • SELECT
    • CONSTRUCT
    • ASK
    • DESCRIBE

ASK


  • ASK queries are used to test whether a query pattern has a solution or not
  • A solution to the query pattern is not returned. The only information that is returned is whether a solution exists or not

Example

Data

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

	_:a  foaf:name       "Alice" .
	_:a  foaf:homepage   <http://work.example.org/alice/> .

	_:b  foaf:name       "Bob" .
	_:b  foaf:mbox       <mailto:bob@work.example> .

Query

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
	ASK  { ?x foaf:name  "Alice" }

Result

true

Query

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
ASK  { ?x foaf:name  "Alice" ;
          foaf:mbox  <mailto:alice@work.example> }

Result

false

DESCRIBE


  • This query form is used to get information/description about RDF resources
  • This is generally used to know the structure of the RDF graph that we are interested in querying
  • The description is determined by the query service. Information can come from the target RDF graph

Example

DESCRIBE <http://example.org/>

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
	DESCRIBE ?x
	WHERE    { ?x foaf:name "Alice" }

Query

PREFIX ent:  <http://org.example.com/employees#>
DESCRIBE ?x WHERE { ?x ent:employeeId "1234" }

Result

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix vcard:  <http://www.w3.org/2001/vcard-rdf/3.0> .
@prefix exOrg:  <http://org.example.com/employees#> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl:  <http://www.w3.org/2002/07/owl#>

_:a     exOrg:employeeId    "1234" ;
       
        foaf:mbox_sha1sum   "bee135d3af1e418104bc42904596fe148e90f033" ;
        vcard:N
         [ vcard:Family       "Smith" ;
           vcard:Given        "John"  ] .

foaf:mbox_sha1sum  rdf:type  owl:InverseFunctionalProperty .

EXISTS


  • It is a filter expression that can be used to test whether a pattern is found in the data
  • It returns true/false and does not generate any additional bindings

Example

Data

@prefix  :  <http://example/> .
@prefix  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .

:alice  rdf:type   foaf:Person .
:alice  foaf:name  "Alice" .
:bob    rdf:type   foaf:Person .

Query

PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX  foaf:  <http://xmlns.com/foaf/0.1/> 

SELECT ?person
WHERE 
{
    ?person rdf:type  foaf:Person .
    FILTER EXISTS { ?person foaf:name ?name }
}

Result

person
<http://example/alice>

Negation

  • There are two ways of using negation in SPARQL
    1. NOT EXISTS: tests for the absense of a pattern
    2. MINUS: removes triples based on a pattern

NOT EXISTS

  • Tests whether a graph pattern does not match the dataset
  • Returns true/false and does not generate any additional bindings

Data

@prefix  :  <http://example/> .
@prefix  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .

:alice  rdf:type   foaf:Person .
:alice  foaf:name  "Alice" .
:bob    rdf:type   foaf:Person .

NOT EXISTS

Query

PREFIX  rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX  foaf:  <http://xmlns.com/foaf/0.1/> 
SELECT ?person
WHERE 
{
    ?person rdf:type  foaf:Person .
    FILTER NOT EXISTS { ?person foaf:name ?name }
}

Result

person
<http://example/bob>

MINUS

  • Assuming the patterns that precede MINUS are left-hand side patterns and the one following MINUS are right-hand side patterns
    • solutions in the LHS that are not compatible with solutions on the RHS are evaluated

Data

@prefix  :  <http://example/> .
@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .

:alice  foaf:givenName "Alice" ;
        foaf:familyName "Smith" .
:bob    foaf:givenName "Bob" ;
        foaf:familyName "Jones" .
:carol  foaf:givenName "Carol" ;
        foaf:familyName "Smith" .

MINUS

Query

PREFIX :  <http://example/> 
PREFIX  foaf:  <http://xmlns.com/foaf/0.1/> 
SELECT DISTINCT ?s
WHERE {
   ?s ?p ?o .
   MINUS {
      ?s foaf:givenName "Bob" .
   }
}

Result

s
<http://example/carol>
<http://example/alice>

Subqueries


  • SPARQL queries can be embedded within another SPARQL query
  • Subqueries are evaluated first and the results are propagated to the outer query
  • Only the variables that are projected out of the subquery will be visible to the outer query

Example

Data

@prefix : <http://people.example/> .

:alice :name "Alice", "Alice Foo", "A. Foo" .
:alice :knows :bob, :carol .
:bob :name "Bob", "Bob Bar", "B. Bar" .
:carol :name "Carol", "Carol Baz", "C. Baz" .

Query

PREFIX : <http://people.example/>
PREFIX : <http://people.example/>
SELECT ?y ?minName
WHERE {
  :alice :knows ?y .
  {
    SELECT ?y (MIN(?name) AS ?minName)
    WHERE {
      ?y :name ?name .
    } GROUP BY ?y
  }
}

Results of inner query

y minName
:alice "A. Foo"
:bob "B. Bar"
:carol "C. Baz"

These are joined with the results of the outer query

y
:bob
:carol

Final Result

y minName
:bob "B. Bar"
:carol "C. Baz"

Demo


References


  1. SPARQL 1.1 Overview. W3C Recommendation.
  2. SPARQL 1.1 Query Language. Steve Harris, and Andy Seaborne. W3C Recommendation.