Search code examples
sparqlrdfsemantic-weblinked-data

Finding a set that contains all values of an original set in a SPARQL query


I'm trying to build a SPARQL query that gets the students of one teacher and finds all the teachers with all those students (they can have more students).

This is what I have so far:

SELECT ?otherTeacher
WHERE {
VALUES ?teacher {$teacher}
  ?teacher hasStudent ?student .
  ?otherTeacher hasStudent ?student .
  FILTER(?teacher <> ?otherTeacher)
}

Here are the expected cases with the below data:
- If teacher1 is given, only teacher3 should show up (teacher3 teaches all the students that teacher1 teaches).
- If teacher2 is given, both teacher1 and teacher3 should show up (both teacher1 and teacher3 teach all the students teacher2 teaches).
- If teacher3 is given, no teachers should show up (no other teacher teaches all the students teacher3 teaches).

<teacher1> <hasStudent> "Alice" .
<teacher1> <hasStudent> "Bob" .
<teacher1> <hasStudent> "Charlie" .
<teacher2> <hasStudent> "Alice" .
<teacher2> <hasStudent> "Dan" .
<teacher3> <hasStudent> "Alice" .
<teacher3> <hasStudent> "Bob" .
<teacher3> <hasStudent> "Charlie" .
<teacher3> <hasStudent> "Dan" .

How do I add a requirement that ?otherTeacher has all the students that ?teacher has (that the new set contains at least all the elements of the original set)?


Solution

  • If one teacher is given, you could try this query:

    SELECT DISTINCT ?otherTeacher
    WHERE {
    VALUES ?teacher {<teacher1> }
      ?otherTeacher <hasStudent> ?student .
      FILTER(?teacher != ?otherTeacher)
      FILTER NOT EXISTS {
        ?teacher <hasStudent> ?s . 
        FILTER NOT EXISTS {?otherTeacher <hasStudent> ?s .}
      }
    }
    

    It uses "double-negation", i.e. it checks that there exists no student of the given teacher that is not taught by the other teacher.