SPARQL Subquery Graph Name - sparql

I have following SPARQL query that contains a sub-select. The data contains multiple graphs and I want to know what graph the values for ?b and ?m come from:
select ?b, ?m, ?g1
where {
{
select ?o1, ?o2, ?e
where{
graph ?g{
?s <http://ndssl.bi.vt.edu/chicago/vocab/dendrogram_infector_pid> ?o1.
?s <http://ndssl.bi.vt.edu/chicago/vocab/dendrogram_infectee_pid> ?o2.
?s <http://ndssl.bi.vt.edu/chicago/vocab/dendrogram_iteration> '0'^^xsd:decimal.
?s <http://ndssl.bi.vt.edu/chicago/vocab/dendrogram_exposureday> ?e.
?s1 <http://ndssl.bi.vt.edu/chicago/vocab/contactnetwork_pid1> ?o1.
?s1 <http://ndssl.bi.vt.edu/chicago/vocab/contactnetwork_pid2> ?o2.
?s1 <http://ndssl.bi.vt.edu/chicago/vocab/contactnetwork_acttype1> '5'^^xsd:decimal.
?s1 <http://ndssl.bi.vt.edu/chicago/vocab/contactnetwork_acttype2> '5'^^xsd:decimal
}
}ORDER BY ASC(?e) LIMIT 1
}
{
graph ?g1 {
?b <http://ndssl.bi.vt.edu/chicago/vocab/getInfectedBy> ?o1.
?m <http://ndssl.bi.vt.edu/chicago/vocab/getInfectedBy>* ?b.
}
}
}
The second graph pattern contains a transitive property path and the query provides following correct result:
b m g1
----------------------------------------------------- ----------------------------------------------------- -------------------------------------------------------
<http://ndssl.bi.vt.edu/chicago/person/pid#446734805> <http://ndssl.bi.vt.edu/chicago/person/pid#446753456> <http://ndssl.bi.vt.edu/chicago/dendrogram/replicate1/>
However, I want to see the intermediate nodes and count the path length from transitive relationship. If I remove graph ?g1 from the query, then it shows the intermediate node information like following:
b m
--------------------------------------------------- ---------------------------------------------------
http://ndssl.bi.vt.edu/chicago/person/pid#446718746 http://ndssl.bi.vt.edu/chicago/person/pid#446718746
http://ndssl.bi.vt.edu/chicago/person/pid#446734805 http://ndssl.bi.vt.edu/chicago/person/pid#446734805
http://ndssl.bi.vt.edu/chicago/person/pid#446734805 http://ndssl.bi.vt.edu/chicago/person/pid#446753456
The Purpose of the query is to figure out graph name for matching ?b and ?m. Hence, I want to use graph ?g1. Is it possible to show intermediate nodes by retaining the graph keyword? I am using Virtuoso.

Since you're not using g the first GRAPH statement is not necessary. Note also that the second GRAPH statement only uses ?o1, so the following query do what you want it to. You may also want to check SPARQL syntax in your select clause.
PREFIX ndssl: <http://ndssl.bi.vt.edu/chicago/vocab/>
SELECT ?b ?m ?g1
WHERE {
{
SELECT ?o1
WHERE {
?s ndssl:dendrogram_infector_pid ?o1 .
?s ndssl:dendrogram_infectee_pid ?o2 .
?s ndssl:dendrogram_iteration '0'^^xsd:decimal .
?s ndssl:dendrogram_exposureday ?e .
?s1 ndssl:contactnetwork_pid1 ?o1 .
?s1 ndssl:contactnetwork_pid2 ?o2 .
?s1 ndssl:contactnetwork_acttype1 '5'^^xsd:decimal .
?s1 ndssl:contactnetwork_acttype2 '5'^^xsd:decimal
} ORDER BY ASC(?e) LIMIT 1
}
GRAPH ?g1 {
?b ndssl:getInfectedBy ?o1 .
?m ndssl:getInfectedBy* ?b .
}
}
In the endpoint provided there isn't a match for ?b or ?m, regardless of whether a GRAPH statement is used or not.

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 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
}
}

Return values under same column in SPARQL query

Given three possible objects for triples, foaf:name, foaf:givenName, and foaf:familyName, where statements either have foaf:name or foaf:givenName + foaf:familyName, e.g.:
<uri1> <foaf:name> "Lolly Loozles" .
<uri2> <foaf:givenName> "Stotly" .
<uri2> <foaf:familyName> "Styles" .
wondering how to write a SPARQL query to return a new variable like pretty_name that is either the value of foaf:name or a concatenation of the values from foaf:givenName and foaf:familyName.
Resulting in something like:
?o | ?pretty_name
----------------------
<uri1> | Lolly Loozles
<uri2> | Stotly Styles
This is what I have so far, but unsure how to proceed:
PREFIX : <https://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
# select two variables, not ideal...
SELECT ?foaf_fullName ?pretty_name
WHERE {
# Find all triples
?s ?p ?o .
# Binds
OPTIONAL { ?s foaf:name ?foaf_fullName }
OPTIONAL { ?s foaf:givenName ?givenName }
OPTIONAL { ?s foaf:familyName ?familyName }
# Filter where predicate is part of list
FILTER (?p IN (foaf:name, foaf:givenName, foaf:familyName ) )
# Binds
BIND( CONCAT(?givenName, ' ', ?familyName) AS ?pretty_name ) .
}
I had imagined, and tried, adding another BIND to add to ?pretty_name, but the SPARQL engine wouldn't have it:
BIND( ?foaf_fullName AS ?pretty_name ) .
I also had luck writing a CONSTRUCT statement to get the values I'm looking for, but don't have the ability to write back to this triplestore (for a number of reasons):
CONSTRUCT {
?s :hasPrettyName ?foaf_fullName .
?s :hasPrettyName ?pretty_name .
}
I had thought that CONSTRUCT could accompany SELECT, but must have been mistaken?
Any insight or suggestions would much appreciated.
Using #StanislavKralin comment/suggestion to use COALESCE without IF clauses works great:
PREFIX : <https://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
# select two variables, not ideal...
SELECT ?foaf_fullName ?pretty_name
WHERE {
# Find all triples
?s ?p ?o .
# Binds
OPTIONAL { ?s foaf:name ?foaf_fullName }
OPTIONAL { ?s foaf:givenName ?givenName }
OPTIONAL { ?s foaf:familyName ?familyName }
# Filter where predicate is part of list
FILTER (?p IN (foaf:name, foaf:givenName, foaf:familyName ) )
# Binds
BIND( COALESCE(?foaf_fullName, CONCAT(?givenName, ' ', ?familyName)) AS ?pretty_name )
}

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 .
}

how to find classes from dbpedia?

I need a sparql query that given a free text (user input),
it finds me from dbpedia all the classes related to it.
How do it?
Also asked here. Accepted answer said --
When you say classes, are you mean about types? If yes, try something like
SELECT ?uri ?label ?type
WHERE {
?uri rdfs:label ?label .
?uri <http://dbpedia.org/ontology/type> ?type .
FILTER regex(str(?label), "Leipzig") .
}
limit 10
I couldn't let this go...
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX virtdrf: <http://www.openlinksw.com/schemas/virtrdf#>
SELECT ?s1c AS ?c1
COUNT (*) AS ?c2
?c3
WHERE
{
QUAD MAP virtrdf:DefaultQuadMap
{
GRAPH ?g
{
?s1 ?s1textp ?o1 .
?o1 bif:contains '"dbpedia"' .
}
}
?s1 a ?s1c .
OPTIONAL { ?s1c rdfs:label ?c3
FILTER(langMatches(LANG(?c3),"EN"))}
}
GROUP BY ?s1c ?c3
ORDER BY DESC (2) ASC (3)
The earlier answer gets you partial results.