Search code examples
sparqlsemantic-weblinked-datatriplesnamed-graphs

SPARQL algebra: tricky ASK from named graphs if any triples do not exist


Take these two named graphs:

# graph :yesterday
:Foo 
     :likes :Bar ;
     :likes :Qux .

# graph :today
:Foo
    :likes :Bar ;
    :likes :Baz .

Now say you want to find out if any of the triples from graph :yesterday are absent from graph :today. How would you ASK this query?

ASK
FROM NAMED :yesterday
FROM NAMED :today
{
    GRAPH :yesterday {
        ?s ?p ?o .
        ...
    }
}

Solution

  • SPARQL has two operations for negation : use the one you find most natural. As I read the problem description, it read more like the first one below to me but in this problem situation they are very similar. They differ in their effects when one part or other of the pattern does not match anything or when there are no variables in common.

    NOT EXISTS tests for the absence of a pattern (there is EXISTS as well). It is a filter applied to each solution of the first pattern. It is like a nested ASK where also that the variables are substituted for the incoming ones to the filter.

    PREFIX : <http://example/>
    SELECT * {
      GRAPH :yesterday { ?s ?p ?o }
      FILTER NOT EXISTS { GRAPH :today { ?s ?p ?o } }
    }
    

    MINUS executes the two patterns (left and right sides) and then returns the rows of the left where there is no matching one anywhere on the right. It is an anti-join.

    PREFIX : <http://example/>
    SELECT * {
      GRAPH :yesterday { ?s ?p ?o }
      MINUS { GRAPH :today { ?s ?p ?o } }
    }
    

    For both I get:

    ------------------------
    | s    | p      | o    |
    ========================
    | :Foo | :likes | :Qux |
    ------------------------
    

    TriG:

    @prefix : <http://example/> .
    
    :yesterday {
      :Foo 
         :likes :Bar ;
         :likes :Qux .
    }
    
    :today {
      :Foo
        :likes :Bar ;
        :likes :Baz .
    }