SPARQL:查找所有子对象都符合条件的对象

SPARQL: find objects with all sub-objects matching a criteria

鉴于此数据,每个人都可以选择有一个 "smart" 谓词,并且每个部门可能有零个或多个人,我需要找到只包含聪明人的部门。结果应该只包括部门 1 和 2。理想情况下,结果还应该包括每个部门的 "smart" 个对象。谢谢!

person:A  p:type  'p' ;
          p:smart 'yes' .
person:B  p:type  'p' ;
          p:smart 'maybe' .
person:C  p:type  'p' .

department:1   p:type 'd' ;
               p:has  person:A, person:B .
department:2   p:type 'd' ;
               p:has  person:B .
department:3   p:type 'd' ;
               p:has  person:B, person:C .
department:4   p:type 'd' .

双重否定之类的东西可能会起作用:

SELECT DISTINCT ?dept WHERE {
  ?dept p:has ?person .
  FILTER NOT EXISTS {
  ?dept p:has ?person1 .
    FILTER NOT EXISTS {
     ?person1 p:smart ?smartVal
    }
  }
}

结果:

+---------------+
|     dept      |
+---------------+
|  department:1 |
|  department:2 |
+---------------+

具有值:

SELECT ?dept (GROUP_CONCAT(DISTINCT ?smart;separator=";") as ?smartValues) WHERE {
  ?dept p:has ?person .
  ?person p:smart ?smart
  FILTER NOT EXISTS {
  ?dept p:has ?person1 .
    FILTER NOT EXISTS {
     ?person1 p:smart ?smartVal
    }
  }
}
GROUP BY ?dept

结果:

+---------------+-------------+
|     dept      | smartValues |
+---------------+-------------+
|  department:1 | maybe;yes   |
|  department:2 | maybe       |
+---------------+-------------+

我觉得我以前回答过类似的问题,但无论如何有一个相当不错的方法来做到这一点:

select ?dept 
   (count(?person) as ?pc) (count(?smart) as ?sc)
   (group_concat(?smart; separator=',') as ?smarts)
{
    ?dept p:has ?person .
    optional { ?person p:smart ?smart }
}
group by ?dept
having (?pc = ?sc)

即:查找部门、人员和(如果可用)智能值。为每个部门找到人数与智能值数量匹配的部门。

-------------------------------------------------------------
| dept                              | pc | sc | smarts      |
=============================================================
| <http://example.com/department#2> | 1  | 1  | "maybe"     |
| <http://example.com/department#1> | 2  | 2  | "yes,maybe" |
-------------------------------------------------------------

当您想获得每个对象的结果时,匹配某些条件,group by / having 通常是最干净的答案(因为您可以将匹配与过滤分开)。