How to bind a variable to a queried item in SPARQL - sparql

In this simple sparql query I get a list of subjects whose object is 42
SELECT ?v WHERE { ?v ?p 42 }
If I add ?p as a variable
SELECT ?v ?p WHERE { ?v ?p 42 }
I will get two entities per row, the subject and the predicate.
What if I wanted three entities, so including the 42? Something like:
SELECT ?v ?p ?m WHERE { ?v ?p (42 as m) }

Another variant is to use BIND, e.g.:
SELECT ?v ?p ?m
WHERE {
BIND(42 AS ?m)
?v ?p ?m
}
The BIND statement simply adds a binding for ?m, which can then be selected for the result set.

In SPARQL 1.1, you can use VALUES for this. You would write
SELECT ?v ?p ?m WHERE {
values ?m { 42 }
?v ?p ?m
}

Standard SPARQL 1.0 does not really allow that. There may be some implementation-specific extensions for doing it, though.
As a workaround, if the data contains a triple with 42 as an object literal, you can do it e.g. like this:
SELECT ?v ?p ?m { ?v ?p 42, ?m FILTER(?m=42)}
which is equivalent with
SELECT ?v ?p ?m WHERE { ?v ?p 42 . ?v ?p ?m FILTER(?m=42)}
as you can write graph patterns sharing the same subject and predicate with the comma object list notation, and the WHERE keyword is optional.
For efficiency, you want to use basic graph patterns to reduce the working triple to a smaller set and only then apply FILTER expressions to further prune the results.

You can accomplish in two ways using BINDINGS keyword as well as FILTER
Using BINDINGS
SELECT ?v ?p ?m
WHERE { ?v ?p ?m}
BINDINGS ?m {(42)}
Using FILTER
SELECT ?v ?p ?m
WHERE {
?v ?p ?m
FILTER (?m = 42)
}

select ?v ?p ?m where { ?v ?p ?m . FILTER( ?m = 42 ) }

I know this is round-about, but I believe this is doable with a subquery.
This is a useful pattern to help you work on the query in the narrow, before you let it loose on your entire dataset:
SELECT ?v ?p ?m WHERE {
{ SELECT 42 as ?m WHERE { } }
?v ?p ?m .
}

Related

How to query the path between two IRI within the same sparql endpoint

How to query the path between two IRI within the same sparql endpoint,Can I control the length and direction of the path.For example, I have some triples,input IRI_A and IRI_B,Can all the paths between IRI_A and IRI_B be detected? now i know that sparql can use this statement,However, the length and direction of the path cannot be controlled
SELECT ?s ?p ?o
WHERE {
GRAPH ?g {
BIND ( <http://localhost/XXX/IRI_A> AS ?start ) .
BIND ( <http://localhost/XXX/IRI_B> AS ?end ) .
?start (<>|!<>)* ?s .
?s ?p ?o .
?o (<>|!<>)* ?end .
}
}
I want to find all the paths between two IRIs

SPARQL: DELETE if subject contains 1 triple and has predicate

I was wondering if anyone knew of a way to DELETE a triple based on 2 conditions:
Subject has a triple count of 1.
The only triple on the subject matches a predicate.
The obstacle I'm coming across with these 2 conditions is that in order to COUNT the number of statements on a subject, you must do GROUP BY ?s. Then you do not have the ability to filter any ?p value.
The most likely solution would be a subquery, but I am not sure how this would be structured.
I would write it like this:
DELETE { ?s ?p ?o }
WHERE {
{
SELECT ?s (COUNT(*) AS ?c) {
?s ?p ?o
}
GROUP BY ?s
}
FILTER (?c = 1)
?s ?p ?o
}
Does something like this work?
I assume that by "Subject has a triple count of 1" you mean that there is only one triple with this subject. For the case of 1, this is a bit easier since we can just check that "there does not exist another triple for the same subject."
DELETE { ?s ?p ?o }
WHERE {
?s ?p ?o
#-- the value of ?p is the predicate of interest.
#-- Alternatively, this could be a FILTER involving
#-- the variable ?p .
values ?p { <the-predicate> }
#-- There is no other triple with ?s as the subject
#-- that has a different subject or object. (I.e.,
#-- the only triple with ?s as a subject is with ?p
#-- and ?o .
filter not exists {
?s ?pp ?oo
filter (?pp != ?p || ?oo != ?o)
}
}

Find orphan nodes with SPARQL

I am trying to find orphan nodes (nodes which do not have any incoming relations) with SPARQL in a Fuseki database.
I tried several queries which all do not return correct results.
I tried the following:
Query 1 (got this from linkedIn)
select ?o ?isOrphan where { GRAPH <http://localhost:8080/catalog/-1305288727> {
?s ?p ?o .
FILTER(!isLiteral(?o))
bind(!(EXISTS {?o ?p1 ?o2}) as ?isOrphan)}}
Query 2
SELECT ?source ?s ?p ?o
WHERE { GRAPH <http://localhost:8080/catalog/-1305288727>{
?s ?p ?o .
FILTER EXISTS {?source ?p ?s } .
}
}
Query 3 - unbound variable pp in FILTER
SELECT ?source ?s ?p ?o
WHERE { GRAPH <http://localhost:8080/catalog/-1305288727>{
?s ?p ?o .
FILTER EXISTS {?source ?pp ?s } .
}
}
Any help is highly appreciated.
This query finds each entity that is the subject of any triple, and then checks that this entity is not the object of any triple.
SELECT ?orphan
FROM <http://localhost:8080/catalog/-1305288727>
WHERE {
?orphan ?p1 [] .
FILTER NOT EXISTS { ?linkingNode ?p2 ?orphan . }
}

SPARQL returning empty result when passing MIN(?date1) from subquery into outer query, with BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)

<This question is now resolved, see comment by Valerio Cocchi>
I am trying to pass a variable from a subquery, that takes the minimum date of a set of dates ?date1 belonging to ?p and passes this to the outer query, which then takes another date ?date2 belonging to ?p (there can be at most 1 ?date2 for every ?p) and subtracts ?minDate from ?date2 to get an integer value for the number of years between. I am getting a blank value for this, i.e. ?diffDate returns no value.
I am using Fuseki version 4.3.2. Here is an example of the query:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}
and an example of the kind of result I am getting:
|-?p----|-----------------?minDate-------------|-----------------?date2------------- |?diffDate|
|<123>|20012-11-22T00:00:00"^^xsd:dateTime|2008-08-18T00:00:00"^^xsd:dateTime| |
I would expect that ?diffDate would give me an integer value. Am I missing something fundamental about how subqueries work in SPARQL?
It seems you have encountered quite an obscure part of the SPARQL spec, namely how BIND works.
Normally SPARQL is evaluated without regard for the position of atoms, i.e.
SELECT *
WHERE {
?a :p1 ?b .
?b :p2 ?c .}
is the same query as:
SELECT *
WHERE {
?b :p2 ?c .
?a :p1 ?b .}
However, BIND is position dependent, so e.g.:
SELECT *
WHERE {
?a :p1 ?b .
BIND(:john AS ?a)}
is not a valid query, whereas:
SELECT *
WHERE {
BIND(:john AS ?a)
?a :p1 ?b .
}
is entirely valid. The same applies to variables used inside of the BIND, which must be declared before the BIND appears.
See here for more.
To go back to your problem, your BIND is using the ?minDate variable before it has been bound, which is why it fails to produce a value for ?diffDate.
This query should do the trick:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate) #Put the BIND after all the variables it uses are bound.
}
Alternatively, you could evaluate the difference in the SELECT, like so:
SELECT ?p ?minDate ?date2 (YEAR(?minDate) - YEAR(?date2) AS ?diffDate)
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}

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.