When running the following query I get only one result as expected
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) .
}
However, I get two results if I query the same code as a subquery:
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) .
}
}
}
According to the documentation the subquery is executed first and the result is then transferred to the outer query, so why does SELECT *
not give the same result?
As explained in the Wikidata documentation here :
The “filter not exists” clause seems to often be inefficient for unclear reasons. To work fine, queries with “filter not exists” often seem to have to be rewritten.
I modified your query and now both queries return the same results :
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
OPTIONAL {?city p:P17 [ wikibase:rank ?rank2 ] .}
FILTER (?rank2 = wikibase:PreferredRank && ?rank != wikibase:PreferredRank) .
FILTER (?rank != wikibase:DeprecatedRank) .
}
}
}
I also checked the ranks of p17 using the following query and wikibase:DeprecatedRank is not the results:
SELECT * WHERE {
wd:Q1748 p:P17 ?o. ?o ?p ?q.
}
wd:Q35 wikibase:PreferredRank
wd:Q756617 wikibase:NormalRank