blob: 9c4a494ab75e5a59e184ce97214763c1cb2a3334 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<title>Apache Jena - SPARQL Tutorial - Optional Information</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="/css/bootstrap-extension.css" rel="stylesheet" type="text/css">
<link href="/css/jena.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="/images/favicon.ico" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="/js/jena-navigation.js" type="text/javascript"></script>
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/js/improve.js" type="text/javascript"></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/index.html">
<img class="logo-menu" src="/images/jena-logo/jena-logo-notext-small.png" alt="jena logo">Apache Jena</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li id="homepage"><a href="/index.html"><span class="glyphicon glyphicon-home"></span> Home</a></li>
<li id="download"><a href="/download/index.cgi"><span class="glyphicon glyphicon-download-alt"></span> Download</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-book"></span> Learn <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-header">Tutorials</li>
<li><a href="/tutorials/index.html">Overview</a></li>
<li><a href="/documentation/fuseki2/index.html">Fuseki Triplestore</a></li>
<li><a href="/documentation/notes/index.html">How-To's</a></li>
<li><a href="/documentation/query/manipulating_sparql_using_arq.html">Manipulating SPARQL using ARQ</a></li>
<li><a href="/tutorials/rdf_api.html">RDF core API tutorial</a></li>
<li><a href="/tutorials/sparql.html">SPARQL tutorial</a></li>
<li><a href="/tutorials/using_jena_with_eclipse.html">Using Jena with Eclipse</a></li>
<li class="divider"></li>
<li class="dropdown-header">References</li>
<li><a href="/documentation/index.html">Overview</a></li>
<li><a href="/documentation/query/index.html">ARQ (SPARQL)</a></li>
<li><a href="/documentation/assembler/index.html">Assembler</a></li>
<li><a href="/documentation/tools/index.html">Command-line tools</a></li>
<li><a href="/documentation/rdfs/">Data with RDFS Inferencing</a></li>
<li><a href="/documentation/geosparql/index.html">GeoSPARQL</a></li>
<li><a href="/documentation/inference/index.html">Inference API</a></li>
<li><a href="/documentation/javadoc.html">Javadoc</a></li>
<li><a href="/documentation/ontology/">Ontology API</a></li>
<li><a href="/documentation/permissions/index.html">Permissions</a></li>
<li><a href="/documentation/extras/querybuilder/index.html">Query Builder</a></li>
<li><a href="/documentation/rdf/index.html">RDF API</a></li>
<li><a href="/documentation/rdfconnection/">RDF Connection - SPARQL API</a></li>
<li><a href="/documentation/io/">RDF I/O</a></li>
<li><a href="/documentation/rdfstar/index.html">RDF-star</a></li>
<li><a href="/documentation/shacl/index.html">SHACL</a></li>
<li><a href="/documentation/shex/index.html">ShEx</a></li>
<li><a href="/documentation/jdbc/index.html">SPARQL over JDBC</a></li>
<li><a href="/documentation/tdb/index.html">TDB</a></li>
<li><a href="/documentation/tdb2/index.html">TDB2</a></li>
<li><a href="/documentation/query/text-query.html">Text Search</a></li>
</ul>
</li>
<li class="drop down">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-book"></span> Javadoc <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/documentation/javadoc.html">All Javadoc</a></li>
<li><a href="/documentation/javadoc/arq/">ARQ</a></li>
<li><a href="/documentation/javadoc_elephas.html">Elephas</a></li>
<li><a href="/documentation/javadoc/fuseki2/">Fuseki</a></li>
<li><a href="/documentation/javadoc/geosparql/">GeoSPARQL</a></li>
<li><a href="/documentation/javadoc/jdbc/">JDBC</a></li>
<li><a href="/documentation/javadoc/jena/">Jena Core</a></li>
<li><a href="/documentation/javadoc/permissions/">Permissions</a></li>
<li><a href="/documentation/javadoc/extras/querybuilder/">Query Builder</a></li>
<li><a href="/documentation/javadoc/shacl/">SHACL</a></li>
<li><a href="/documentation/javadoc/tdb/">TDB</a></li>
<li><a href="/documentation/javadoc/text/">Text Search</a></li>
</ul>
</li>
<li id="ask"><a href="/help_and_support/index.html"><span class="glyphicon glyphicon-question-sign"></span> Ask</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-bullhorn"></span> Get involved <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/getting_involved/index.html">Contribute</a></li>
<li><a href="/help_and_support/bugs_and_suggestions.html">Report a bug</a></li>
<li class="divider"></li>
<li class="dropdown-header">Project</li>
<li><a href="/about_jena/about.html">About Jena</a></li>
<li><a href="/about_jena/architecture.html">Architecture</a></li>
<li><a href="/about_jena/citing.html">Citing</a></li>
<li><a href="/about_jena/team.html">Project team</a></li>
<li><a href="/about_jena/contributions.html">Related projects</a></li>
<li><a href="/about_jena/roadmap.html">Roadmap</a></li>
<li class="divider"></li>
<li class="dropdown-header">ASF</li>
<li><a href="http://www.apache.org/">Apache Software Foundation</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Become a Sponsor</a></li>
<li><a href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li>
<li><a href="http://www.apache.org/security/">Security</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
</ul>
</li>
<li id="edit"><a href="https://github.com/apache/jena-site/edit/main/source/tutorials/sparql_optionals.md" title="Edit this page on GitHub"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="breadcrumbs">
<ol class="breadcrumb">
<li><a href='/tutorials'>TUTORIALS</a></li>
<li class="active">SPARQL OPTIONALS</li>
</ol>
</div>
<h1 class="title">SPARQL Tutorial - Optional Information</h1>
<p>RDF is semi-structured data so SPARQL has a the ability to query
for data but not to fail query when that data does not exist. The
query is using an optional part to extend the information found in
a query solution but to return the non-optional information
anyway.</p>
<h2 id="optionals">OPTIONALs</h2>
<p>This query (<a href="sparql_data/q-opt1.rq">q-opt1.rq</a>) gets the name of a person and
also their age if that piece of information is available.</p>
<pre><code>PREFIX info: &lt;http://somewhere/peopleInfo#&gt;
PREFIX vcard: &lt;http://www.w3.org/2001/vcard-rdf/3.0#&gt;
SELECT ?name ?age
WHERE
{
?person vcard:FN ?name .
OPTIONAL { ?person info:age ?age }
}
</code></pre>
<p>Two of the four people in the data (<a href="sparql_data/vc-db-2.rdf">vc-db-2.rdf</a>)have
age properties so two of the query solutions have that
information.  However, because the triple pattern for the age is
optional, there is a pattern solution for the people who don&rsquo;t have
age information.</p>
<pre><code>------------------------
| name | age |
=======================
| &quot;Becky Smith&quot; | 23 |
| &quot;Sarah Jones&quot; | |
| &quot;John Smith&quot; | 25 |
| &quot;Matt Jones&quot; | |
-----------------------
</code></pre>
<p>If the optional clause had not been there, no age information would
have been retrieved. If the triple pattern had been included but
not optional then we would have the query
(<a href="sparql_data/q-opt2.rq">q-opt2.rq</a>):</p>
<pre><code>PREFIX info: &lt;http://somewhere/peopleInfo#&gt;
PREFIX vcard: &lt;http://www.w3.org/2001/vcard-rdf/3.0#&gt;
SELECT ?name ?age
WHERE
{
?person vcard:FN ?name .
?person info:age ?age .
}
</code></pre>
<p>with only two solutions:</p>
<pre><code>-----------------------
| name | age |
=======================
| &quot;Becky Smith&quot; | 23 |
| &quot;John Smith&quot; | 25 |
-----------------------
</code></pre>
<p>because the <code>info:age</code> property must now be present in a solution.</p>
<h2 id="optionals-with-filters">OPTIONALs with FILTERs</h2>
<p><code>OPTIONAL</code> is a binary operator that combines two graph patterns.
The optional pattern is any group pattern and may involve any
SPARQL pattern types.  If the group matches, the solution is
extended, if not, the original solution is given
(<a href="sparql_data/q-opt3.rq">q-opt3.rq</a>).</p>
<pre><code>PREFIX info: &lt;http://somewhere/peopleInfo#&gt;
PREFIX vcard: &lt;http://www.w3.org/2001/vcard-rdf/3.0#&gt;
SELECT ?name ?age
WHERE
{
?person vcard:FN ?name .
OPTIONAL { ?person info:age ?age . FILTER ( ?age &gt; 24 ) }
}
</code></pre>
<p>So, if we filter for ages greater than 24 in the optional part, we
will still get 4 solutions (from the <code>vcard:FN</code> pattern) but only
get ages if they pass the test.</p>
<pre><code>-----------------------
| name | age |
=======================
| &quot;Becky Smith&quot; | |
| &quot;Sarah Jones&quot; | |
| &quot;John Smith&quot; | 25 |
| &quot;Matt Jones&quot; | |
-----------------------
</code></pre>
<p>No age included for &ldquo;Becky Smith&rdquo; because it is less than 24.</p>
<p>If the filter condition is moved out of the optional part, then it
can influence the number of solutions but it may be necessary to
make the filter more complicated to allow for variable <code>age</code> being
unbound (<a href="sparql_data/q-opt4.rq">q-opt4.rq</a>).</p>
<pre><code>PREFIX info: &lt;http://somewhere/peopleInfo#&gt;
PREFIX vcard: &lt;http://www.w3.org/2001/vcard-rdf/3.0#&gt;
SELECT ?name ?age
WHERE
{
?person vcard:FN ?name .
OPTIONAL { ?person info:age ?age . }
FILTER ( !bound(?age) || ?age &gt; 24 )
}
</code></pre>
<p>If a solution has an <code>age</code> variable, then it must be greater than
24. It can also be unbound.  There are now three solutions:</p>
<pre><code>-----------------------
| name | age |
=======================
| &quot;Sarah Jones&quot; | |
| &quot;John Smith&quot; | 25 |
| &quot;Matt Jones&quot; | |
-----------------------
</code></pre>
<p>Evaluating an expression which has an unbound variables where a
bound one was expected causes an evaluation exception and the whole
expression fails.</p>
<h2 id="optionals-and-order-dependent-queries">OPTIONALs and Order Dependent Queries</h2>
<p>One thing to be careful of is using the same variable in two or
more optional clauses (and not in some basic pattern as well):</p>
<pre><code>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX vCard: &lt;http://www.w3.org/2001/vcard-rdf/3.0#&gt;
SELECT ?name
WHERE
{
?x a foaf:Person .
OPTIONAL { ?x foaf:name ?name }
OPTIONAL { ?x vCard:FN ?name }
}
</code></pre>
<p>If the first optional binds <code>?name</code> and <code>?x</code> to some values, the
second <code>OPTIONAL</code> is an attempt to match the ground triples (<code>?x</code>
and <code>?name</code> have values). If the first optional did not
match the optional part, then the second one is an attempt to match
its triple with two variables.</p>
<p>With an example set of data in which every combination of values exist:</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#008000;font-weight:bold">&lt;rdf:RDF</span>
<span style="color:#b44">xmlns:rdf=</span><span style="color:#b44">&#39;http://www.w3.org/1999/02/22-rdf-syntax-ns#&#39;</span>
<span style="color:#b44">xmlns:vCard=</span><span style="color:#b44">&#39;http://www.w3.org/2001/vcard-rdf/3.0#&#39;</span>
<span style="color:#b44">xmlns:info=</span><span style="color:#b44">&#39;http://somewhere/peopleInfo#&#39;</span>
<span style="color:#b44">xmlns:foaf=</span><span style="color:#b44">&#39;http://xmlns.com/foaf/0.1/&#39;</span>
<span style="color:#008000;font-weight:bold">&gt;</span>
<span style="color:#080;font-style:italic">&lt;!-- both vCard:FN and foaf:name have values, and the values are the same --&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:Person</span> <span style="color:#b44">rdf:about=</span><span style="color:#b44">&#34;http://somewhere/JohnSmith&#34;</span><span style="color:#008000;font-weight:bold">&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;vCard:FN&gt;</span>John Smith<span style="color:#008000;font-weight:bold">&lt;/vCard:FN&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:name&gt;</span>John Smith<span style="color:#008000;font-weight:bold">&lt;/foaf:name&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;/foaf:Person&gt;</span>
<span style="color:#080;font-style:italic">&lt;!-- both vCard:FN and foaf:name have values, but the values are not the same --&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:Person</span> <span style="color:#b44">rdf:about=</span><span style="color:#b44">&#34;http://somewhere/RebeccaSmith&#34;</span><span style="color:#008000;font-weight:bold">&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;vCard:FN&gt;</span>Becky Smith<span style="color:#008000;font-weight:bold">&lt;/vCard:FN&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:name&gt;</span>Rebecca Smith<span style="color:#008000;font-weight:bold">&lt;/foaf:name&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;/foaf:Person&gt;</span>
<span style="color:#080;font-style:italic">&lt;!-- only vCard:FN has values --&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:Person</span> <span style="color:#b44">rdf:about=</span><span style="color:#b44">&#34;http://somewhere/SarahJones&#34;</span><span style="color:#008000;font-weight:bold">&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;vCard:FN&gt;</span>Sarah Jones<span style="color:#008000;font-weight:bold">&lt;/vCard:FN&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;/foaf:Person&gt;</span>
<span style="color:#080;font-style:italic">&lt;!-- only foaf:name has values --&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:Person</span> <span style="color:#b44">rdf:about=</span><span style="color:#b44">&#34;http://somewhere/MattJones&#34;</span><span style="color:#008000;font-weight:bold">&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:name&gt;</span>Matthew Jones<span style="color:#008000;font-weight:bold">&lt;/foaf:name&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;/foaf:Person&gt;</span>
<span style="color:#080;font-style:italic">&lt;!-- neither vCard:FN nor foaf:name have values --&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;foaf:Person</span> <span style="color:#b44">rdf:about=</span><span style="color:#b44">&#34;http://somewhere/AdamJones&#34;</span> <span style="color:#008000;font-weight:bold">/&gt;</span>
<span style="color:#008000;font-weight:bold">&lt;/rdf:RDF&gt;</span>
</code></pre></div><p>Executing the above query will yield these solutions:</p>
<pre><code>-------------------
| name |
===================
| &quot;John Smith&quot; |
| &quot;Matthew Jones&quot; |
| &quot;Sarah Jones&quot; |
| |
| &quot;Rebecca Smith&quot; |
-------------------
</code></pre>
<p><a href="sparql_union.html">Next: union queries</a></p>
</div>
</div>
</div>
<footer class="footer">
<div class="container" style="font-size:80%" >
<p>
Copyright &copy; 2011&ndash;2022 The Apache Software Foundation, Licensed under the
<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
</p>
<p>
Apache Jena, Jena, the Apache Jena project logo, Apache and the Apache feather logos are trademarks of
The Apache Software Foundation.
<br/>
<a href="https://privacy.apache.org/policies/privacy-policy-public.html"
>Apache Software Foundation Privacy Policy</a>.
</p>
</div>
</footer>
<script type="text/javascript">
var link = $('a[href="' + this.location.pathname + '"]');
if (link != undefined)
link.parents('li,ul').addClass('active');
</script>
</body>
</html>