对 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)
我需要为 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)