SPARQL: How to obtain label in available languages if first option is not available
Asked Answered
G

1

8

If a Wikidata resource returned by my query has no available label in the language I filtered for I obtained an empty cell.

SELECT *
WHERE
{
    ?country wdt:P31 wd:Q6256.
    ?country rdfs:label ?country_name
        FILTER(LANG(?country_name) = 'jbo').
}

link

How to request to have a label returned in one of any of the available languages if the first language fails?

Greeley answered 13/7, 2016 at 11:8 Comment(0)
G
7

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
   }
}
Gronseth answered 13/7, 2016 at 12:57 Comment(2)
This doesn't sound like a great solution to me. If the country label is available in 270 languages, out of which 3 are variants of English, this will return 810 results, all containing the same label (because the 3 English ones are the same). This is exactly what happens for Canada (add bind (wd:Q16 as ?country) to the query).Myrmeco
@Myrmeco Ah yes, that should be select distinct... The other option (mentioned in one of the linked questions/answers) that's probably just as good, is to use two optionals that bind the same variable. I've updated my answer with the better option.Gronseth

© 2022 - 2024 — McMap. All rights reserved.