Search code examples
rdfsparql

SPARQL query to construct sub-graph with select paths (paths have different lengths)


Is it possible to CONSTRUCT an RDF sub-graph that contains nodes A, B, C, E, F (but no D, G, H) from the following graph using a single SPARQL query:

:A :p :B .
:A :q :C .
:A :r :D .
:A :s :E . :E :t :F .
:A :u :G . :G :v :H .

I know how to formulate a SPARQL query that returns { A-p-B, A-q-C } (i.e. two paths consisting of 1 statement each) and one that returns { A-s-E E-t-F } (i.e. one path consisting of 2 statements). But it it possible to fold both into as single SPARQL CONSTRUCT query and if so, how would that look?


Solution

  • It's much easier to work with data if you provide it in a legal RDF serialization, so that we can easily run queries against it. Here's your data in a form that we can actually query against:

    @prefix : <http://stackoverflow.com/q/20840883/1281433/> .
    
    :A :p :B .
    :A :q :C .
    :A :r :D .
    :A :s :E . :E :t :F .
    :A :u :G . :G :v :H .
    

    If you just want the subgraph induced by the nodes A, B, C, E, and F, you can simply ask for all triples where both the subject and object are taken from that set. E.g.:

    prefix : <http://stackoverflow.com/q/20840883/1281433/>
    
    construct {
      ?s ?p ?o
    } 
    where { 
        values ?s { :A :B :C :E :F }
        values ?o { :A :B :C :E :F }
        ?s ?p ?o 
    }
    

    This produces the following result (in your notation, in N3, and in RDF/XML):

    A-p-B
    A-q-C
    A-s-E E-t-F
    
    @prefix :      <http://stackoverflow.com/q/20840883/1281433/> .
    
    :E      :t      :F .
    
    :A      :p      :B ;
            :q      :C ;
            :s      :E .
    
    <rdf:RDF
        xmlns="http://stackoverflow.com/q/20840883/1281433/"
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about="http://stackoverflow.com/q/20840883/1281433/A">
        <s>
          <rdf:Description rdf:about="http://stackoverflow.com/q/20840883/1281433/E">
            <t rdf:resource="http://stackoverflow.com/q/20840883/1281433/F"/>
          </rdf:Description>
        </s>
        <q rdf:resource="http://stackoverflow.com/q/20840883/1281433/C"/>
        <p rdf:resource="http://stackoverflow.com/q/20840883/1281433/B"/>
      </rdf:Description>
    </rdf:RDF>