2

I have this SPARQL code that is meant to work on Wikidata:

SELECT
  ?game
  (group_concat(distinct      ?gameLabel ; separator = ", ") AS      ?gameLabels)
  (group_concat(distinct     ?genreLabel ; separator = ", ") AS     ?genreLabels)
  WHERE {
    ?game wdt:P31 wd:Q7889;
    wdt:P136 wd:Q744038.
    OPTIONAL {?game wdt:P136     ?genre}
    SERVICE wikibase:label {
      bd:serviceParam wikibase:language "en".
           ?game rdfs:label      ?gameLabel.
          ?genre rdfs:label     ?genreLabel.
    }
  }
GROUP BY $game
ORDER BY ASC (?gameLabels)

You can test the code here:

https://query.wikidata.org/

Suppose that ?genreLabel is always lower case by default. How do I capitalize the first letter of each returned value? Thanks.

logi-kal
  • 7,107
  • 6
  • 31
  • 43
posfan12
  • 2,541
  • 8
  • 35
  • 57

1 Answers1

2

That's the point where things are getting complicated with the magic label SERVICE of Wikidata because you can't use them in BIND parts - or least I don't know how:

SELECT
  ?game
  (group_concat(distinct      ?gameLabel ; separator = ", ") AS      ?gameLabels)
  (group_concat(distinct     ?genreL ; separator = ", ") AS     ?genreLabels)

  WHERE {
    ?game wdt:P31 wd:Q7889 ;
          wdt:P136 wd:Q744038 .
    OPTIONAL {
       ?game wdt:P136     ?genre. 
       ?genre rdfs:label ?gL. 
       FILTER(LANGMATCHES(LANG(?gL), "en"))
    }
    BIND(CONCAT(UCASE(SUBSTR(?gL, 1, 1)), SUBSTR(?gL, 2)) as ?genreL)

    SERVICE wikibase:label {
      bd:serviceParam wikibase:language "en".
           ?game rdfs:label      ?gameLabel.
    }

  }
GROUP BY ?game
ORDER BY ASC (?gameLabels)

The idea is as follows:

  • take the first character of the label: SUBSTR(?gL, 1, 1)
  • apply the upper case operator on it: UCASE(SUBSTR(?gL, 1, 1))
  • take the whole string starting from the second character: SUBSTR(?gL, 2))
  • concatenate both parts: CONCAT(UCASE(SUBSTR(?gL, 1, 1)), SUBSTR(?gL, 2))

Note, at some point, it might be easier to do String modification and styling on the client side...

UninformedUser
  • 8,397
  • 1
  • 14
  • 23
  • This is slightly off-topic, but some game titles are in English, British English and Canadian English. (I have no idea why.) How do I filter just for regular English using the LANGMATCHES command? `FILTER(LANGMATCHES(LANG(...), "en"))` does not seem to be sufficient. Thanks. – posfan12 May 28 '17 at 11:18
  • 1
    Right, the `LANGMATCHES` functions is used to be agnostic regarding the range for a language, i.e. it matches British English as well as American English, etc. To avoid those duplicates, simply don't use `LANGMATCHES`, i.e. `FILTER(LANG(?gL) = "en")` – UninformedUser May 28 '17 at 11:29