Search code examples
sparqlwikidata

Can't filter on terminological codes for ISO 639-2


On wikidata, with the following query:

SELECT ?item ?code
WHERE { ?item wdt:P219 ?code }  # ISO 639-2 code (P219)

I find all languages that are defined in ISO 639-2, but for certains languages (for example French), I got 2 different codes (fra and fre).

This is normal according to ISO 639-2 as it define terminological and bibliographical codes.

Now my question is how do I filter to only get one of them?

I tried to do the following:

SELECT ?item ?code
WHERE { ?item wdt:P219 ?code.  # ISO 639-2 code (P219)
        ?code wdt:P518 wd:Q1725664.}  # applies to part (P518), terminology (Q1725664)

as mention on the french item (https://www.wikidata.org/wiki/Q150#identifiers)

enter image description here

but I didn’t get any result.

I suspect it’s because fre and fra (and thus ?code) are strings and not item, but I still need a solution to filter on terminological codes.


Solution

  • So you have two options: The first one, as in the comment, is to use the sample function. This will work if you don't care whether you use the terminological or bibliographical code. The query is then:

    SELECT ?item (SAMPLE(?code) AS ?sampleCode)
    WHERE {
    ?item wdt:P219 ?code
    }
    GROUP BY ?item
    

    If instead you want to choose a particular code, in this case the terminological one, you need to use a similar approach to the one you already had.

    SELECT ?item ?code
    WHERE { ?item p:P219 ?codeStatement.  # ISO 639-2 code (P219)
            ?codeStatement pq:P518 wd:Q1725664 ; # applies to part (P518), terminology (Q1725664)
                           ps:P219 ?code}  
    

    The difference between the above and your approach lies in the namespaces used. Here I use p:, ps:, and pq:, instead of just wdt:.

    The difference is that they lead us to a statement about a triple.

    We use p:P219 to find all the statements concerning P219, and ps:219 to find the object of those statements. So:

    SELECT ?item ?code
    WHERE{
    ?item wdt:P219 ?code}
    

    will have the exact same results as:

    SELECT DISTINCT ?item ?code
    WHERE{
    ?item p:P219 ?codestatement .
    ?codestatement ps:P219 ?code.}
    

    If we then want to add further restrictions to the statements (e.g. it must only apply to terminology), then we use the pq: namespace, together with the appropriate property, in this case P518.