First, prefer langMatches for checking language tags. This is especially important in your case, since you might want, for instance, a label in English, and langMatches(lang(?label), "en") will find a label with the tag "en", or "en-GB", or "en-US", etc. Those are regional variants for the language, and langMatches can help you find them.
Updated Solution based on comments
@svick noticed in the comments that the original solution ends up with a row for each element in the Cartesian product of the English names with the non-English names. You can avoid that by using a select distinct. But there's really a better way: just use the same variable in two optionals; the first checks for an English label, and the second checks for non-English labels. If the first succeeds, then the second never gets invoked. That is, just do:
select ?country ?label {
?country wdt:P31 wd:Q6256
optional {
?country rdfs:label ?label
filter langMatches(lang(?label), "en")
}
optional {
?country rdfs:label ?label
}
}
Other options
Original Solution with COALESCE
After that, though, coalesce will do what you want. It takes a number of arguments, and returns the first one that has a value. So, you can match the preferred language in an optional block, and any language in another, and coalesce the values:
select distinct ?country (coalesce(?enLabel, ?anyLabel) as ?label) {
?country wdt:P31 wd:Q6256
optional {
?country rdfs:label ?enLabel
filter langMatches(lang(?enLabel), "en")
}
optional {
?country rdfs:label ?anyLabel
}
}
bind (wd:Q16 as ?country)
to the query). – Myrmeco