一个SPARQL查询,用于返回满足某些条件的实体

时间:2018-05-09 08:54:46

标签: sparql rdf semantic-web

我需要编写一个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)

对于所有记录

,此查询在?cnt下返回值0

2 个答案:

答案 0 :(得分:3)

我建议采用以下天真的做法。

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)。

答案 1 :(得分:2)

可能应该详细说明我在上述评论中建议使用的UNION。例如检索与第一个条件相匹配的所有内容,并且至少保留其中一个条件,或者第二个条件成立的解决方案,以及最后两个存在于一起的其他两个OR解决方案中的至少一个,如下所示:

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,然后使用HAVING过滤掉不想要的东西:

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)