Sparql: Arithmetic operators between variables? - sparql

Hi I have a query like this:
SELECT ?a ?b
WHERE
{
?c property:name "myThing"#en
?c property:firstValue ?b
?c property:secondValue ?a
}
How can I divide the first nuber and the second? idealy somthing like this:
SELECT ?a/?b
WHERE
{
?c property:name "myThing"#en
?c property:firstValue ?b
?c property:secondValue ?a
}
Thank you

In SPARQL 1.1 you can do it using Project expressions like so:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT (xsd:float(?a)/xsd:float(?b) AS ?result)
WHERE
{
?c property:name "myThing"#en
?c property:firstValue ?b
?c property:secondValue ?a
}
You may alternately use xsd:double(?var) to cast to a double, xsd:integer(?var) to cast to an integer and xsd:decimal(?var) to cast to a decimal.
Note that SPARQL specifies type promotion rules so for example:
integer / integer = decimal
float / double = double
If you really need the result in a guaranteed datatype you can cast the whole divide expression e.g.
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT (xsd:double(xsd:float(?a)/xsd:float(?b)) AS ?result)
WHERE
{
?c property:name "myThing"#en
?c property:firstValue ?b
?c property:secondValue ?a
}

There are two ways to achieve this:
SELECT ((?a/?b) AS ?result) WHERE {
?c property:name "myThing"#en .
?c property:firstValue ?b .
?c property:secondValue ?a .
}
or
SELECT ?result WHERE {
BIND((?a/?b) AS ?result) .
?c property:name "myThing"#en .
?c property:firstValue ?b .
?c property:secondValue ?a .
}

Related

Querying two RDF graphs in SPARQL

I have two RDF knowledge bases
KB1 (path/to/file1.rdf) wkich includes the two following triples
a b c
a f e
and KB2 (path/to/file2.rdf) with the following triple:
c t p
I want to get all paths include ones like ?a ?b ?c & ?c ?t ?p as c is common.
How can I do that in SPARQL?
In case of two KB, it is what we call a "Federated Query". Here is an example :
SELECT * WHERE {
SERVICE URI_for_path/to/file1.rdf {
?a ?b ?c .
OPTIONAL {
SERVICE URI_for_path/to/file2.rdf {
?c ?t ?p . } }
}
}
You will get ?t ?p only if it exists by the way.
Simpliest way is to load both files in a single KB and therefore have a simple query :
SELECT * WHERE {
?a ?b ?c .
?c ?t ?p .
}

Sparql query issue with DBpedia retrieving

I'm trying to run this Sparql statement to read data from DBpedia; However, it only return the column names and no row data.
If anybody can let me know what's the issue. I'll be more appreciated
Sparql query below:
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?actor ?movie ?director ?movie_date
WHERE {
?m dc:subject <http://dbpedia.org/resource/Category:American_films> .
?m rdfs:label ?movie .
FILTER(LANG(?movie) = "en")
?m dbp:released ?movie_date .
FILTER(DATATYPE(?movie_date) = xsd:date)
?m dbp:starring ?a .
?a rdfs:label ?actor .
FILTER(LANG(?actor) = "en")
?m dbp:director ?d .
?d rdfs:label ?director .
FILTER(LANG(?director) = "en")
}
The problem is not all the queried triples exist. If at least one of the relations doesnt exist, no result will be given.
So with the OPTIONAL keyword, answers will be given only if they exist and wont block your query if they don't. It simply leaves the missing value empty.
PREFIX dbp: <http://dbpedia.org/property/>
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?actor ?movie ?director ?movie_date
WHERE {
?m dc:subject <http://dbpedia.org/resource/Category:American_films> .
OPTIONAL{
?m rdfs:label ?movie .
FILTER(LANG(?movie) = "en") }
OPTIONAL {
?m dbp:released ?movie_date .
FILTER(DATATYPE(?movie_date) = xsd:date) }
OPTIONAL{
?m dbp:starring ?a .
?a rdfs:label ?actor .
FILTER(LANG(?actor) = "en") }
OPTIONAL{
?m dbp:director ?d .
?d rdfs:label ?director .
FILTER(LANG(?director) = "en") }
}

SPARQL generate Values for missing fields

I´m trying to write a SELECT, that gives me all the Values in a Table. I have optional Values, I want those to be filled with a standard value, If they don´t exist.
This is my code:
SELECT * WHERE {
?a nmo:hasObject nm:coin
OPTIONAL
{ ?a nmo:hasAuthority ?b }
OPTIONAL
{ ?a nmo:hasMaterial ?c }}
What I get id the following:
?a ?b ?c
1 yx
2 ab
3 xz bc
What I want is to fill it up with the String "missing" if there is no value:
?a ?b ?c
1 yx "missing"
2 "missing" ab
3 xz bc
Any ideas on how to structure the SELECT to get this output?
I'd probably use coalesce here:
SELECT
?a
(coalesce (?b, ?missing) as ?bb)
(coalesce (?c, ?missing) as ?cc)
WHERE {
VALUES ?missing { "missing" }
?a nmo:hasObject nm:coin
OPTIONAL
{ ?a nmo:hasAuthority ?b }
OPTIONAL
{ ?a nmo:hasMaterial ?c }
}
SPARQL 1.1 BIND in combination with IF can be used to achieve this:
SELECT * WHERE
{ ?a nmo:hasObject nm:coin
OPTIONAL
{ ?a nmo:hasAuthority ?b_tmp }
OPTIONAL
{ ?a nmo:hasMaterial ?c_tmp }
BIND(if(bound(?b_tmp), ?b_tmp, "missing") AS ?b)
BIND(if(bound(?c_tmp), ?c_tmp, "missing") AS ?c)
}

SPARQL group concat union

I'm trying to GROUP_CONCAT a UNION of two sets of triples.
Is this not allowed?
PREFIX bo: <https://webfiles.uci.edu/jenniyk2/businessontology#>
SELECT (GROUP_CONCAT(DISTINCT ?m2;SEPARATOR = ", ") AS ?comp)
WHERE
{
{{SELECT ?m2 ?c ?p
WHERE { ?c rdfs:label ?m. ?c2 rdfs:label ?m2. ?so bo:owner ?p.
?so bo:sharesIn ?c. ?so2 bo:owner ?p. ?so2 bo:sharesIn ?c2. }
}
UNION
{SELECT ?m2 ?c ?p
WHERE { ?c rdfs:label ?m. ?c2 rdfs:label ?m2. ?dir bo:isPartOf ?c.
?dir bo:isDirectedBy ?p. ?dir2 bo:isPartOf ?c2. ?dir2 bo:isDirectedBy ?p.}
}}
GROUP BY ?c
HAVING (COUNT(?m2) >1)}
It says there's an error in the very last line.
Found group. Was expecting one of : BIND, BLANK_NODE_LABEL, DECIMAL,
DOUBLE, FALSE, FILTER, GEO, GRAPH, INTEGER, MINUS, NIL-SYMBOL, OPTIONAL,
Q_IRI_REF, QNAME, QNAME_NS, SERVICE, STRING_LITERAL1, STRING_LITERAL2,
STRING_LITERAL_LONG1, STRING_LITERAL_LONG2, TEXTINDEX, TRUE, UNION, VALUES,
VARNAME or punctuation '(', '+', '-', '.', '[', '[]', '{', '}'.
The GROUP BY and HAVING clauses should be outside the WHERE clause, not inside it as they currently are. To make your query syntactically correct, remove the closing } from the last line and add it on the line above your GROUP BY:
PREFIX bo: <https://webfiles.uci.edu/jenniyk2/businessontology#>
SELECT (GROUP_CONCAT(DISTINCT ?m2;SEPARATOR = ", ") AS ?comp)
WHERE
{
{{SELECT ?m2 ?c ?p
WHERE { ?c rdfs:label ?m. ?c2 rdfs:label ?m2. ?so bo:owner ?p.
?so bo:sharesIn ?c. ?so2 bo:owner ?p. ?so2 bo:sharesIn ?c2. }
}
UNION
{SELECT ?m2 ?c ?p
WHERE { ?c rdfs:label ?m. ?c2 rdfs:label ?m2. ?dir bo:isPartOf ?c.
?dir bo:isDirectedBy ?p. ?dir2 bo:isPartOf ?c2. ?dir2 bo:isDirectedBy ?p.}
}}}
GROUP BY ?c
HAVING (COUNT(?m2) >1)
As Joshua also indicated, the query can be written a lot simpler, but this should solve your immediate problem.
Jeen Broekstra's answer identifies the typographical problem that causes your syntax error, but I think it's worth mentioning that this query can be simplified a bit, because simpler code from the beginning makes it easier to spot typos and syntax errors when they arise. If I read it correctly, it looks like the body of the query simplifies to this:
?c rdfs:label ?m .
?c2 rdfs:label ?m2 .
{ ?so bo:owner ?p ;
bo:sharesIn ?c .
?so2 bo:owner ?p ;
bo:sharesIn ?c2 . }
union
{ ?dir bo:isPartOf ?c ;
bo:isDirectedBy ?p .
?dir2 bo:isPartOf ?c2 ;
bo:isDirectedBy ?p }
You're looking for a ?c that's connected by one of two certain types of path to a ?c2, and you want to group by ?c and concatenate the distinct labels of ?c2. I see two ways that this could be simplified further. The first is with the use of property paths, since you don't actually use the values of many of these variables. With property paths, the body could become:
?c rdfs:label ?m .
?c2 rdfs:label ?m2 .
{ ?c ^bo:sharesIn/bo:owner/^bo:owner/bo:sharesIn ?c2 }
union
{ ?c ^bo:isPartOf/bo:isDirectedBy/^bo:isDirectedBy/bo:isPartOf ?c2 }
As another alternative, since the structure of the pattern in each union alternative is similar, you could abstract a bit with values:
?c rdfs:label ?m .
?c2 rdfs:label ?m2 .
values (?sharesIn_isPartOf ?owner_isDirectedBy) {
(bo:sharesIn bo:owner)
(bo:isPartOf bo:isDirectedBy)
}
?x ?owner_isDirectedBy ?y ;
?sharesIn_isPartOf ?c .
?x2 ?owner_isDirectedBy ?y ;
?sharesIn_isPartOf ?c2 .

Restrict property from being rdf:type

In a query like this, how can I avoid ?p being bound to rdf:type?
select ?p ?c where {
<http://dbpedia.org/resource/Istance_1> ?p ?c.
<http://dbpedia.org/resource/Istance_2> ?p ?c.
}
Add a filter to your query:
select ?p ?c where {
<http://dbpedia.org/resource/Istance_1> ?p ?c.
<http://dbpedia.org/resource/Istance_2> ?p ?c.
filter( ?p != rdf:type )
}
It's typical to use the prefix dbpedia: for http://dbpedia.org/resource/, and I expect that Istance is suppose to be Instance, so with a bit of cleanup, you'll have
prefix dbpedia: <http://dbpedia.org/resource>
select ?p ?c where {
dbpedia:Instance_1 ?p ?c .
dbpedia:Instance_2 ?p ?c .
filter( ?p != rdf:type )
}
If you're copying and pasting into the public DBpedia SPARQL endpoint, you won't need to define that prefix because it, and bunch of others are predefined, but if you'll calling it some other fashion, you will need to.