在 SPARQL 查询中查找包含原始集合的所有值的集合

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

我正在尝试构建一个 SPARQL 查询,该查询获取一位教师的学生并找到所有教师 所有 这些学生(他们可以有更多学生)。

这是我目前拥有的:

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

以下是具有以下数据的预期案例:
- 如果给出了 teacher1,则只有 teacher3 应该出现(teacher3 教所有 teacher1 教的学生)。
- 如果给出了teacher2,teacher1和teacher3都应该出现(teacher1和teacher3都教teacher2教的所有学生)。
- 如果给出了 teacher3,则不应出现任何老师(没有其他老师会教 teacher3 教的所有学生)。

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

如何添加要求:?otherTeacher 拥有 ?teacher 拥有的所有学生(新集合至少包含原始集合的所有元素)?

如果指定了一位老师,您可以试试这个查询:

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

它使用"double-negation",即检查是否存在给定老师的学生没有被其他老师教过。

这不是一个优雅的解决方案,因为它涉及嵌套多个查询。应该有更好的方法来解决这个问题。

此解决方案使用嵌套查询来获取计数的最大值。
第 13 行只包括 otherTeacher 的学生,该老师也教过(从计数中删除像 Dan 这样的学生)。

select distinct ?otherTeacher
where{
  {
    select (max(?count) as ?max)
      where{
        {
          SELECT DISTINCT ?otherTeacher (COUNT(?student) as ?count)
          WHERE {
          VALUES ?teacher {<teacher1> }
            ?otherTeacher <hasStudent> ?student .
            FILTER(?teacher != ?otherTeacher)
            FILTER EXISTS {
              ?teacher <hasStudent> ?student . 
            }
          }
          group by ?otherTeacher
       }
    }
  }
  {
    SELECT DISTINCT ?otherTeacher (COUNT(?student) as ?count)
    WHERE {
    VALUES ?teacher {<teacher1> }
      ?otherTeacher <hasStudent> ?student .
      FILTER(?teacher != ?otherTeacher)
      FILTER EXISTS {
        ?teacher <hasStudent> ?student . 
      }
    }
    group by ?otherTeacher
  }
  filter(?count >= ?max) # epsilon error/no match if it's equal?
}