I'm transforming the data in one data store to another form / ontology / schema, using SPARQL.
The data is actually a provenance, but can be simplified as a series of relationship like this: A produces D + B consumes D.
:A0 :consumes :D0 ;
:produces :D1, :D2 .
:A1 :produces :D3 .
:A2 :consumes :D1, :D2 ;
:produces :D4 .
:A3 :consumes :D3, :D4 ;
:produces :D5, D6 .
(There is no guarantee D is always produced by some A, or will be consumed by some other A. But every D will only be produced by one A.)
I would like to get the information of data dependency. An example query looks like this:
CONSTRUCT {
?producer :hasNextStage ?consumer .
}
WHERE {
?producer :produces ?data .
OPTIONAL {
?consumer :consumes ?data .
FILTER (?producer != ?consumer)
}
}
Everything is fine until here. However, I would like to have more information, say "which A is connected to which another A by what data", something like this:
:A0 :hasInfluence :INFLUENCE .
:INFLUENCE :stage :A2 ;
:data :D1, :D2 .
As demonstrated, this requires me to construct a new variable (:INFLUENCE) and assign triples to it.
Is there a way to do this in SPARQL?
------ UPDATED SECONDARY QUESTION ------
According to cygri's answer, I changed the query to this:
CONSTRUCT {
?producer :hasInfluence ?influence .
?influence :stage ?consumer ;
:data ?data .
}
WHERE {
?producer :produces ?data .
OPTIONAL {
?consumer :consumes ?data .
FILTER (?producer != ?consumer)
BIND (IRI(CONCAT("http://my/ns/#", CONCAT(STRAFTER(STR(?producer), "#"), STRAFTER(STR(?consumer), "#")))) AS ?influence)
}
}
However, the BIND clause seems not having any effect. After shortening it, the problem is with the ?producer variable: if I use this variable here, it won't work. Seems ?producer is not bound here? (But the FILTER does work.)
If I move this BIND clause out of the OPTIONAL, everything works fine. But this is not intuitive, and I'm wondering why it won't work inside OPTIONAL?
IRI()to create a URI resource from a string. Or just put the IRI there if you know it – UninformedUser Apr 1 '19 at 17:08OPTIONALis a left-outer join during evaluation. The clause is evaluated separately. Read about scope of variables: w3.org/TR/sparql11-query/#variableScope – UninformedUser Apr 2 '19 at 12:10(leftjoin (bgp (triple ?producer <http://ex.org/test/produces> ?data)) (extend ((?influence (iri (concat "http://my/ns/#" (concat (strafter (str ?producer) "#") (strafter (str ?consumer) "#")))))) (bgp (triple ?consumer <http://ex.org/test/consumes> ?data))) (!= ?producer ?consumer))– UninformedUser Apr 2 '19 at 12:17BINDoutside of theOPTIONAL:(extend ((?influence (iri (concat "http://my/ns/#" (concat (strafter (str ?producer) "#") (strafter (str ?consumer) "#")))))) (conditional (bgp (triple ?producer <http://ex.org/test/produces> ?data)) (filter (!= ?producer ?consumer) (bgp (triple ?consumer <http://ex.org/test/consumes> ?data)))))– UninformedUser Apr 2 '19 at 12:18BINDand the scope: blog.blazegraph.com/?p=954 - and I agree, without knowing this, it is definitely confusing – UninformedUser Apr 2 '19 at 12:19