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