对 return 个满足某些条件的实体的 SPARQL 查询

A SPARQL query to return entities that satisfy some of the conditions

我需要为 return 满足固定数量条件(并非总是所有条件)的实体编写 SPARQL 查询。我的想法是,我需要获得满足所提供的 4 个条件中的 2 个条件的所有实体。我正在编写以下查询

SELECT ?ent WHERE {
    BIND(0 as ?cnt).
    OPTIONAL {
       ?ent ns:age ?age.
       FILTER(?age > 20 && ?age <= 40).
       BIND(?cnt + 1, ?cnt).
    }.
    OPTIONAL {
        ?ent ns:livesIn nst:Mauritius.
        BIND(?cnt + 1, ?cnt).
    }.
    OPTIONAL {
        ?ent ns:maritalStatus nst:Married.
        BIND(?cnt + 1, ?cnt).
    }.
    OPTIONAL {
        ?ent ns:fatherIs/ns:age ?fatherAge.
        FILTER(?fatherAge > 55 && ?fatherAge <= 80).
        BIND(?cnt + 1, ?cnt).
    }
} HAVING(?cnt > 2)

我是否以正确的方式解决问题?我错过了什么吗?有没有更好的方法来解决我的问题?

编辑 1:上面提到的查询给了我一个错误。现在我正在尝试这个

SELECT ?ent ?cnt WHERE {
    BIND(0 as ?cnt1).
    BIND(0 as ?cnt2).
    BIND(0 as ?cnt3).
    BIND(0 as ?cnt4).
    OPTIONAL {
       ?ent ns:age ?age.
       FILTER(?age > 20 && ?age <= 40).
       BIND(1 as ?cnt1).
    }.
    OPTIONAL {
        ?ent ns:livesIn nst:Mauritius.
        BIND(1 as ?cnt2).
    }.
    OPTIONAL {
        ?ent ns:maritalStatus nst:Married.
        BIND(1 as ?cnt3).
    }.
    OPTIONAL {
        ?ent ns:fatherIs/ns:age ?fatherAge.
        FILTER(?fatherAge > 55 && ?fatherAge <= 80).
        BIND(1 as ?cnt4).
    }
    BIND((?cnt1 + ?cnt2 + ?cnt3 + ?cnt4) as ?cnt)
} ORDER BY DESC(?cnt)

此查询 return所有记录的 ?cnt 下的值为 0

我建议采用以下幼稚的方法。

SELECT ?ent ?cnt WHERE {
    ?ent a foaf:Person .
    OPTIONAL {
        ?ent ns:age ?age.
        FILTER(?age > 20 && ?age <= 40).
    }
    OPTIONAL {
        ?ent ns:livesIn ?livesIn.
        FILTER (?livesIn = nst:Mauritius)
    }
    OPTIONAL {
        ?ent ns:maritalStatus ?maritalStatus.
        FILTER (?maritalStatus = nst:Married).
    }
    OPTIONAL {
        ?ent ns:fatherIs/ns:age ?fatherAge.
        FILTER(?fatherAge > 55 && ?fatherAge <= 80).
    }
    BIND(xsd:integer(bound(?age)) +
         xsd:integer(bound(?livesIn)) +
         xsd:integer(bound(?maritalStatus)) +
         xsd:integer(bound(?fatherAge))
         AS ?cnt)
    FILTER (?cnt > 2)
} ORDER BY DESC(?cnt)

您最近的查询有两个问题:

  • 外部 BIND 覆盖内部(或者更确切地说,它们之间没有连接)。
  • 您从 OPTIONAL 开始(请参阅 In SPARQL, order matters)。

可能应该详细说明我在上述评论中建议的 UNION 的使用。例如检索与第一个条件匹配的所有内容,并且至少满足其余条件之一,或者满足第二个条件的解决方案,并且至少满足其他两个条件之一,或者最后两个条件同时存在的解决方案,所以类似这样:

SELECT ?ent WHERE {
{
    ?ent ns:age ?age.
    FILTER(?age > 20 && ?age <= 40).
    {
        ?ent ns:livesIn nst:Mauritius.
    } union {
        ?ent ns:maritalStatus nst:Married.
    } union {
            ?ent ns:fatherIs/ns:age ?fatherAge.
            FILTER(?fatherAge > 55 && ?fatherAge <= 80).
    }
} union {
    ?ent ns:livesIn nst:Mauritius.
    {
        ?ent ns:maritalStatus nst:Married.
    } union {
            ?ent ns:fatherIs/ns:age ?fatherAge.
            FILTER(?fatherAge > 55 && ?fatherAge <= 80).
    }    
} union {
    ?ent ns:maritalStatus nst:Married.
    ?ent ns:fatherIs/ns:age ?fatherAge.
    FILTER(?fatherAge > 55 && ?fatherAge <= 80).
  }
}

另一种可能的方法是使用 GROUP BY over ?ent,但这只有在每个 OPTIONAL 块中的每个解决方案恰好是一个时才有效,然后查询是所有条件之间的简单 UNION,然后使用必须过滤掉不需要的内容:

SELECT ?ent WHERE {
{
    ?ent ns:age ?age.
    FILTER(?age > 20 && ?age <= 40).
} union {
    ?ent ns:livesIn nst:Mauritius.
} union {
    ?ent ns:maritalStatus nst:Married.
} union {
        ?ent ns:fatherIs/ns:age ?fatherAge.
        FILTER(?fatherAge > 55 && ?fatherAge <= 80).
}
} GROUP BY ?ent
HAVING (count(*) > 1)