SPARQL直接查询与子查询结果不一致问题咨询
SPARQL子查询嵌套后结果数量不符的问题
单独执行以下SPARQL查询时,符合预期仅返回1条结果:
SELECT DISTINCT ?city ?country WHERE { FILTER (?city = wd:Q1748) . # Primary country ?city p:P17 ?c . ?c ps:P17 ?country ; wikibase:rank ?rank . FILTER NOT EXISTS { ?c pq:P582 [] . } # Existing countries only FILTER NOT EXISTS { ?city p:P17 [ wikibase:rank ?rank2 ] . FILTER (?rank2 = wikibase:PreferredRank && ?rank != wikibase:PreferredRank) . } FILTER (?rank != wikibase:DeprecatedRank) . }
但将该查询作为子查询嵌套在外层SELECT *查询中时,却返回2条结果:
SELECT * WHERE { { SELECT DISTINCT ?city ?country WHERE { FILTER (?city = wd:Q1748) . # Primary country ?city p:P17 ?c . ?c ps:P17 ?country ; wikibase:rank ?rank . FILTER NOT EXISTS { ?c pq:P582 [] . } # Existing countries only FILTER NOT EXISTS { ?city p:P17 [ wikibase:rank ?rank2 ] . FILTER (?rank2 = wikibase:PreferredRank && ?rank != wikibase:PreferredRank) . } FILTER (?rank != wikibase:DeprecatedRank) . } } }
原因分析
核心问题出在子查询的变量绑定和SELECT列表的不匹配:
- 子查询里用到了
?rank变量进行过滤,但没有把它包含在SELECT DISTINCT的字段列表中。子查询的DISTINCT只会对?city和?country的组合去重,所以返回1条结果。 - 但SPARQL子查询在执行时,内部所有被绑定的变量(包括
?rank)其实都会被保留在结果集中,只是子查询的输出只展示了?city和?country。当外层用SELECT *时,会把子查询结果集中所有存在的变量(包括?rank)都返回。 - 实际场景中,子查询内部可能存在两条记录:
?city和?country完全相同,但?rank的值不同(比如一个是wikibase:PreferredRank,一个是wikibase:NormalRank)。子查询因为只去重?city和?country,所以输出1条;但外层查询会把这两条带不同?rank的记录都输出,最终得到2条结果。
解决办法
有两种方式可以让外层查询结果和子查询一致:
- 把子查询的
SELECT DISTINCT改为SELECT DISTINCT ?city ?country ?rank,让?rank也参与去重,此时子查询返回的结果数量就是最终结果数量。 - 外层查询不要用
SELECT *,而是明确指定需要的字段:SELECT ?city ?country,这样只会输出子查询中指定的字段,自动忽略?rank的差异。
内容的提问来源于stack exchange,提问作者Bjørn RL
相关产品推荐
相关产品推荐

