1
SPARQL
Part III
Jan Pettersen Nytun, UiA
SPARQL Part III Jan Pettersen Nytun, UiA 1 S Agenda O P - - PowerPoint PPT Presentation
SPARQL Part III Jan Pettersen Nytun, UiA 1 S Agenda O P Example with: - ORDER BY - SUM Example continues with: - GROUP BY - GROUP BY together with SUM Example continues with: - HAVING - BIND - CONCAT New example with:
1
Jan Pettersen Nytun, UiA
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 2
S O
P
Jan Pettersen Nytun, UIA, page 3
4
S O
P
Jan Pettersen Nytun, UIA, page 5
S O
P
Jan Pettersen Nytun, UIA, page 6
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#>
SELECT ?employee ?year ?amount WHERE { … }
S O
P
Jan Pettersen Nytun, UIA, page 7
?salary ?employee :hasSalary
SELECT ?employee ?year ?amount WHERE { ?employee :hasSalary :salary }
S O
P
Jan Pettersen Nytun, UIA, page 8
?employee :hasSalary ?salary
Totally 6 matches:
:bob :hasSalary :bobSalaray2013 . :bob :hasSalary :bobSalaray2014 . …
S O
P
What if some other types of resources have salaries?
Jan Pettersen Nytun, UIA, page 9
Employee ?employee rdf:type
SELECT ?employee ?year ?amount WHERE { ?employee :hasSalary ?salary .
?employee rdf:type :Employee }
:hasSalary ?salary
S O
P
Jan Pettersen Nytun, UIA, page 10
Employee ?employee rdf:type :hasSalary ?salary Totally 6 matches, but showing only one match: Again there are 6 matches. Showing one of them:
(composed of 2 triples):
:bob :hasSalary :bobSalaray2014 . :bob rdf:type :Employee .
S O
P
Jan Pettersen Nytun, UIA, page 11
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#>
SELECT ?employee ?year ?amount WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount}
S O
P
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#>
SELECT ?employee ?year ?amount WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount} ORDER BY ?year
Jan Pettersen Nytun, UIA, page 12
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 13
S O
P
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#>
SELECT (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount}
Jan Pettersen Nytun, UIA, page 14
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 15
S O
P
Jan Pettersen Nytun, UIA, page 16
S O
P
Jan Pettersen Nytun, UIA, page 17
WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount} :e1 :hasSalary :s1 . :s1 :hasYear “2001”. :s1 :hasAmount “100” .
Assume this gives the following 4 matches:
:e2 :hasSalary :s2 . :s2 :hasYear “2003”. :s2 :hasAmount “200” . :e3 :hasSalary :s3 . :s3 :hasYear “2003”. :s3 :hasAmount “1300” . :e4 :hasSalary :s4 . :s4 :hasYear “2001”. :s4 :hasAmount “400” .
[3] By default a solution set consists of a single group, containing all solutions.
S O
P
SELECT … WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount} GROUP BY ?year
Jan Pettersen Nytun, UIA, page 18
S O
P
page 19
WHERE { … } GROUP BY ?year
:e1 :hasSalary :s1 . :s1 :hasYear “2001”. :s1 :hasAmount “100” .
Gives 2 groups:
:e2 :hasSalary :s2 . :s2 :hasYear “2003”. :s2 :hasAmount “200” . :e3 :hasSalary :s3 . :s3 :hasYear “2003”. :s3 :hasAmount “1300” . :e4 :hasSalary :s4 . :s4 :hasYear “2001”. :s4 :hasAmount “400” .
:e1 :hasSalary :s1 . :s1 :hasYear “2001”. :s1 :hasAmount “100” . :e2 :hasSalary :s2 . :s2 :hasYear “2003”. :s2 :hasAmount “200” . :e3 :hasSalary :s3 . :s3 :hasYear “2003”. :s3 :hasAmount “1300” . :e4 :hasSalary :s4 . :s4 :hasYear “2001”. :s4 :hasAmount “400” .
S O
P
Aggregates apply expressions over groups of solutions. Aggregates defined in version 1.1 of SPARQL are COUNT, SUM, MIN, MAX, AVG, ... SELECT ?year (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount} GROUP BY ?year
Jan Pettersen Nytun, UIA, page 20
S O
P
page 21
SELECT ?year (SUM (?amount) AS ?total) ….
Gives 2 results:
year total 2001 500 2003 1500
:e1 :hasSalary :s1 . :s1 :hasYear “2001”. :s1 :hasAmount “100” . :e2 :hasSalary :s2 . :s2 :hasYear “2003”. :s2 :hasAmount “200” . :e3 :hasSalary :s3 . :s3 :hasYear “2003”. :s3 :hasAmount “1300” . :e4 :hasSalary :s4 . :s4 :hasYear “2001”. :s4 :hasAmount “400” .
S O
P
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#>
SELECT ?year (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount} GROUP BY ?year
page 22
S O
P
Jan Pettersen Nytun, UIA, page 23
24 @prefix : <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary#> . @prefix owl: <http://www.w3.org/2002/07/owl#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix xml: <http://www.w3.org/XML/1998/namespace> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @base <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary> . <http://www.uia.no/ikt437/janpettersennytun/ontologies/salary> rdf:type owl:Ontology . :hasSalary rdf:type owl:ObjectProperty ; rdfs:domain :Employee ; rdfs:range :Salary . :hasAmount rdf:type owl:DatatypeProperty ; rdfs:range xsd:int . :hasName rdf:type owl:DatatypeProperty . :hasYear rdf:type owl:DatatypeProperty ; rdfs:range xsd:int .
S O
P
How to see the salaries summed up for each employees by year [4]
SELECT ?year ?employee (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount } GROUP BY ?year ?employee
Jan Pettersen Nytun, UIA, page 25
S O
P
SELECT ?year ?employee (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount } GROUP BY ?year ?employee ORDER BY ?year ?employee
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 27
S O
P
SELECT ?year ?employee (SUM (?amount) AS ?total) WHERE { ?employee :hasSalary ?salary . ?salary :hasYear ?year . ?salary :hasAmount ?amount } GROUP BY ?year ?employee HAVING (?total > 250000) ORDER BY ?year ?employee
Jan Pettersen Nytun, UIA, page 28
Old query result:
S O
P
[4]: HAVING and FILTER are very similar ... FILTER refers to variables bound within a particular graph pattern … always appears in the pattern (between “{“ and ”}”), while HAVING refers to variables defined by aggregations in the SELECT clause, and hence always appears outside a graph pattern.
Jan Pettersen Nytun, UIA, page 29
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 30
S O
P
[4]: An assignment lets the query write specifically the value of a variable through some computation—“assigning” a value to that variable, rather than matching some value in the data.
Jan Pettersen Nytun, UIA, page 31
S O
P :Bart :hasParent :Homer . :Bart :hasParent :Marge .
:Lisa :hasParent :Homer . :Lisa :hasParent :Marge . :Maggie :hasParent :Homer . :Maggie :hasParent :Marge . :Ling :hasParent :Selma .
###:Herb :hasParent :Abraham . :Herb :hasParent :Mona . :Homer :hasParent :Abraham . :Homer :hasParent :Mona . :Marge :hasParent :Clancy . :Marge :hasParent :Jackie . :Patty :hasParent :Clancy . :Patty :hasParent :Jackie . :Selma :hasParent :Clancy . :Selma :hasParent :Jackie .
###:Abraham :gender :male . :Mona :gender :female . :Clancy :gender :male . :Jackie :gender :female . :Herb :gender :male . :Homer :gender :male . :Marge :gender :female . :Patty :gender :female . :Selma :gender :female .
:Bart :gender :male .
:Lisa :gender :female . :Maggie :gender :female . :Ling :gender :female .
[http://www.englishexercises.org/makeagame/viewgame.asp?id=4]
@prefix : www.simpsons.no/simpsonsfamily
S O
P
Jan Pettersen Nytun, UIA, page 33
2 Etc.
S O
P
PREFIX : <http://www.simpsons.no/simpsonsfamily#> PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> SELECT ?grandmother WHERE { :Maggie :hasParent ?parent. ?parent :hasMother ?grandmother } ORDER BY ?grandmother
Jan Pettersen Nytun, UIA, page 34
2 Etc.
S O
PPREFIX : <http://www.simpsons.no/simpsonsfamily#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> SELECT ?grandchildName ?grandmother WHERE { :Maggie foaf:name ?grandchildName . :Maggie :hasParent ?parent. ?parent :hasMother ?grandmother } ORDER BY ?grandmother
Jan Pettersen Nytun, UIA, page 35
2 Etc.
S O
PPREFIX : <http://www.simpsons.no/simpsonsfamily#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> SELECT ?grandchildName ?grandmother WHERE { :Maggie :hasParent ?parent. ?parent :hasMother ?grandmother BIND ("some name" as ?grandchildName) } ORDER BY ?grandmother
Jan Pettersen Nytun, UIA, page 36
2 Etc.
S O
P
Jan Pettersen Nytun, UIA, page 37
[3]:
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 38
S O
P
SELECT (concat (?first, " ", ?last) AS ?fullname) WHERE { :WorkingOntologist dc:creator ?author . ?author :firstName ?first . ?author :lastName ?last . }
page 39
[4]: [3]:
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 40
S O
P
page 41
?grandchild :hasParent ?parent . ?parent :hasParent ?grandfather .
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX : <http://uia.no/fame#> SELECT ?grandchild ?grandfather WHERE { ?grandchild :hasParent ?parent . ?parent :hasParent ?grandfather . ?grandfather :gender :male }
S O
P
SPARQL CONSTRUCT allows us to specify templates of new information based on patterns found in old information… sometimes called a Rule… “Whenever you see this, conclude that.” Example.: If John’s father is Joe, then Joe’s son is John
Jan Pettersen Nytun, UIA, page 44
S O
P
single RDF graph specified by a graph template.
Jan Pettersen Nytun, UIA, page 45
46
CONSTRUCT QUERY
Returns a single RDF graph specified by a graph template
S O
P
USING RESULTS OF CONSTRUCT QUERIES [4]
Sophisticated RDF query systems provide workbenches … a variety of options for what to do with constructed triples:
graph…
(in another database)…
Jan Pettersen Nytun, UIA, page 47
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 48
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX : <http://uia.no/fame#> INSERT {?grandchild :hasGrandFather ?grandfather } WHERE { ?grandchild :hasParent ?parent . ?parent :hasParent ?grandfather . ?grandfather :gender :male }
<http://uia.no/fame#Bart> <http://uia.no/fame#hasGrandFather> <http://uia.no/fame#Abraham> .
Adds to ontology:
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 51
52
DELETE Statement
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 53
S O
P
Construct all nephew-uncle triples given the following triples:
:Ester rdf:type :Woman ; :hasBrother :Olav , :Sigmund . :Jan rdf:type :Man ; :hasParent :Sigmund . :Kirsten rdf:type :Woman ; :hasParent :Sigmund . :Olav rdf:type :Man ; :hasSister :Ester ; :hasBrother :Sigmund . :Sigmund rdf:type :Man ; :hasSister :Ester . :Sigrund rdf:type :Woman ; :hasParent :Sigmund . The following triples should be produced: :Jan :hasUncle :Olav. :Kirsten :hasUncle :Olav.
Jan Pettersen Nytun, UIA, page 54
(The niece/nephew-ant relations are ignored.)
S O
P
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> CONSTRUCT {?n :hasUncle ?uncle} WHERE { ?n :hasParent ?parent. ?parent :hasBrother ?uncle }
Jan Pettersen Nytun, UIA, page 55
:Ester rdf:type :Woman ; :hasBrother :Olav , :Sigmund . :Jan rdf:type :Man ; :hasParent :Sigmund . :Kirsten rdf:type :Woman ; :hasParent :Sigmund . :Olav rdf:type :Man ; :hasSister :Ester ; :hasBrother :Sigmund . :Sigmund rdf:type :Man ; :hasSister :Ester . :Sigrund rdf:type :Woman ; :hasParent :Sigmund .
S O
P
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> CONSTRUCT {?n :hasUncle ?uncle} WHERE { ?n :hasParent ?parent. ?parent :hasBrother ?uncle }
Jan Pettersen Nytun, UIA, page 56
:Ester rdf:type :Woman ; :hasBrother :Olav , :Sigmund . :Jan rdf:type :Man ; :hasParent :Sigmund . :Kirsten rdf:type :Woman ; :hasParent :Sigmund . :Olav rdf:type :Man ; :hasSister :Ester ; :hasBrother :Sigmund . :Sigmund rdf:type :Man ; :hasSister :Ester . :Sigrund rdf:type :Woman ; :hasParent :Sigmund .
Change order of ?parent and ?uncle in last triple of the WHERE-clause and there will be match on :Olav :hasBrother :Sigmund . However, one could add triple :Sigmund :hasBrother :Olav . to the RDF data.
S O
P
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> CONSTRUCT {?n :hasUncle ?uncle} WHERE { ?n :hasParent ?parent. ?uncle :hasBrother ?parent. ?uncle rdf:type :Man. }
Jan Pettersen Nytun, UIA, page 57
:Ester rdf:type :Woman ; :hasBrother :Olav , :Sigmund . :Jan rdf:type :Man ; :hasParent :Sigmund . :Kirsten rdf:type :Woman ; :hasParent :Sigmund . :Olav rdf:type :Man ; :hasSister :Ester ; :hasBrother :Sigmund . :Sigmund rdf:type :Man ; :hasSister :Ester . :Sigrund rdf:type :Woman ; :hasParent :Sigmund .
S O
P
A graph pattern is made up of several triples—all
match… there is an implicit “and” operation between the triples… if we want one “or” another triple to match we may use UNION (if both match then there will be two different matches).
Jan Pettersen Nytun, UIA, page 58
S O
P
Use UNION to fix the following:
Jan Pettersen Nytun, UIA, page 59
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> CONSTRUCT {?n :hasUncle ?uncle} WHERE { ?n :hasParent ?parent. ?parent :hasBrother ?uncle }
We need an or (i.e., UNION) between “?parent :hasBrother ?uncle” and “?uncle :hasBrother ?parent”
S O
P
Jan Pettersen Nytun, UIA, page 60
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> CONSTRUCT {?n :hasUncle ?uncle} WHERE {?n :hasParent ?parent.
{?uncle :hasBrother ?parent.} UNION {?parent :hasBrother ?uncle } .
?uncle rdf:type :Man. }
:Ester rdf:type :Woman ; :hasBrother :Olav , :Sigmund . :Jan rdf:type :Man ; :hasParent :Sigmund . :Kirsten rdf:type :Woman ; :hasParent :Sigmund . :Olav rdf:type :Man ; :hasSister :Ester ; :hasBrother :Sigmund . :Sigmund rdf:type :Man ; :hasSister :Ester; :hasBrother :Rolf . :Sigrund rdf:type :Woman ; :hasParent :Sigmund . :Rolf rdf:type :Man.
S O
P
[4] Mapping several related relationships (mother, father, son, daughter) onto a single hierarchy (parent); CONSTRUCT {?s :hasParent ?o} WHERE{ {?s :hasMother ?o} UNION {?s :hasFather ?o} UNION {?o :hasSon ?s} UNION {?o :hasDaughter ?s}}
Jan Pettersen Nytun, UIA, page 61
S O
P
Example with:
Example continues with:
Example continues with:
New example with:
page 62
S O
P
Jan Pettersen Nytun, UIA, page 63
Aggregates apply expressions over groups
By default a solution set consists of a single group, containing all solutions. Grouping may be specified using the GROUP BY. Aggregates: COUNT, SUM, MIN,….
S O
P
[3]: Count is a SPARQL set function which counts the number of times a given expression has a bound ... [4]: For example, we could find out how many movies James Dean has played in: SELECT (COUNT (?movie) AS ?howmany) WHERE {:JamesDean ?playedIn ?movie .}
Jan Pettersen Nytun, UIA, page 64
S O
P
Jan Pettersen Nytun, UIA, page 65
S O
P
PREFIX : <http://www.uia.no/janpettersennytun/ontologies/family#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> SELECT DISTINCT (COUNT (?uncle) AS ?numberOfUnclesForJan) WHERE { :Jan :hasParent ?parent. {?uncle :hasBrother ?parent.} UNION {?parent :hasBrother ?uncle } . ?uncle rdf:type :Man. }
Jan Pettersen Nytun, UIA, page 66
S O
P
Jan Pettersen Nytun, UIA, page 67
[1] Book: David Poole and Alan Mackworth, Artificial Intelligence: Foundations of Computational Agents, Cambridge University Press, 2010, http://artint.info/ [2] http://www.w3.org/TR/swbp-n-aryRelations/ [3] SPARQL 1.1 Query Language, W3C Recommendation 21 March 2013, http://www.w3.org/TR/2013/REC-sparql11-query-20130321/ [4] Semantic Web for the Working Ontologist, Second Edition: Effective Modeling in RDFS and OWL, May 20, 2011, by Dean Allemang, James Hendler [5] Appreciating SPARQL CONSTRUCT more, Bob DuCharme's weblog, http://www.snee.com/bobdc.blog/2009/09/appreciating-sparql-construct.html