As @AKSW has noted, the query that correctly returns all countries is:
SELECT ?country ?countryLabel
WHERE
{
?country p:P31/ps:P31 wd:Q6256 .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ASC(?countryLabel)
The only difference from your query is the line ?country p:P31/ps:P31 wd:Q6256 .
The slash (/
) in that line is a shorthand notation. The line can be expanded as:
?country p:P31 ?statement .
?statement ps:P31 wd:Q6256 .
The prefixes p:
and ps:
are namespaces. Wikidata's convention is to keep entity-to-statement connectors in the p
namespace and statement-to-value connectors in the ps
namespace. They must be linked together to query for the list of countries.
This may seem like a lot of complexity. You just want to find countries; you don't care about statements about countries. Thus, the wdt:
prefix was created for use cases like yours. This namespace is supposed to summarize p:/ps:
linkages for these simple yes-or-no queries.
But there's a problem! To quote from the Wikidata SPARQL docs:
Such triples, using the wdt:
representation of the property, are not created for all statements, but for only statements that have the highest rank for the property on that item and are not deprecated. While not being guaranteed to be true, they are intended to summarise Wikidata's best current understanding of the truth.
In short, the wdt:
namespace is incomplete and you found some of the holes. For whatever reason, a handful of countries like Suriname and Russia got left out of the statements in that namespace.
EDIT: This seems to have something to do with being assigned as a "country" or as a "sovereign state". Using Q3624078
, the sovereign state identifier, instead of Q6256
also fixes your query.