0

When I run the following query I get multiple rows of "Paul Gauguin" since there are multiple informations about his place/time of death, the same could of course happen on all other parameters as well.

   SELECT DISTINCT ?item ?itemLabel ?itemDescription ?birthplaceLabel ?birthdate ?deathplaceLabel ?deathdate ?imageLabel ?article ?articleEn
{
  ?item wdt:P31 wd:Q5.
  ?item wdt:P119 wd:Q5024152.
  
  OPTIONAL {
    ?item wdt:P18 ?image.       
  }
  OPTIONAL {
    ?item wdt:P19 ?birthplace.
  }
  OPTIONAL {
    ?item wdt:P569 ?birthdate.    
  }
  OPTIONAL {
    ?item wdt:P20 ?deathplace.    
  }
  OPTIONAL {
    ?item wdt:P570 ?deathdate.
  }
  OPTIONAL {
     ?article schema:about ?item.
     ?article schema:isPartOf <https://sv.wikipedia.org/>.
  }
   OPTIONAL {
     ?articleEn schema:about ?item.
     ?articleEn schema:isPartOf <https://en.wikipedia.org/>.
  }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "sv,en, [AUTO_LANGUAGE]". }
}

Is there a way of only recive one of the same object id, and don't care about if there are other "versions" of the object.

I have tried a bit with nested queries but I can't get it to work. Are there som other ways?

  • this only works with the usage of aggregate functions. So you `group by` the `item` and then you have to do it for all the other values. The question here is, how do you handle multiple values of his place for example. This will result in which aggregate function you have to use – UninformedUser Mar 10 '21 at 17:44

2 Answers2

1

This query will work:

SELECT DISTINCT ?item ?itemLabel ?itemDescription 
(SAMPLE(?birthplaceLabel) AS ?birthplaceLabel)
(SAMPLE(?birthdate) AS ?birthdate)
(SAMPLE(?deathplaceLabel) AS ?deathplaceLabel)
(SAMPLE(?deathdate) AS ?deathdate)
(SAMPLE(STR(?image)) AS ?image)
?article ?articleEn

WHERE {
  ?item wdt:P31 wd:Q5.
  ?item wdt:P119 wd:Q5024152.
  
  OPTIONAL {
    ?item wdt:P18 ?image.       
  }
  OPTIONAL {
    ?item wdt:P19 ?birthplace.
  }
  OPTIONAL {
    ?item wdt:P569 ?birthdate.    
  }
  OPTIONAL {
    ?item wdt:P20 ?deathplace .    
  }
  OPTIONAL {
    ?item wdt:P570 ?deathdate.
  }
  OPTIONAL {
     ?article schema:about ?item.
     ?article schema:isPartOf <https://sv.wikipedia.org/>.
  }
   OPTIONAL {
     ?articleEn schema:about ?item.
     ?articleEn schema:isPartOf <https://en.wikipedia.org/>.
  }
  SERVICE wikibase:label {  ?birthplace rdfs:label ?birthplaceLabel . 
                          ?deathplace rdfs:label ?deathplaceLabel .
                          ?item rdfs:label ?itemLabel ;
                                schema:description ?itemDescription .
                          bd:serviceParam wikibase:language "sv,en, [AUTO_LANGUAGE]". }
}
GROUP BY ?item ?itemLabel ?itemDescription ?article ?articleEn

As you can see, we use the SAMPLE function and group by all the variables that aren't sampled. You could also replace SAMPLE with GROUP_CONCAT if you wish to see all the possible values taken by a property. E.g. ... (GROUP_CONCAT(?deathdate; SEPARATOR="; ") AS ?deathdates) ...

Note that GROUP_CONCAT takes strings as arguments.

Valerio Cocchi
  • 1,891
  • 1
  • 6
  • 18
  • Thanks! But then "birthplaceLabel", "deathhplaceLabel" and "imageLabel" is empty in the result, I guess since there is many "versions" of this. Would it be possible to get let say the "first" value of one of these in the result? Just so there is something to display on the site, the user would then go to Wikipedia and could read about all the other possible "birthdates" and/or see the rest of the images, – Mårten Swärd Mar 10 '21 at 19:19
  • Oh right, sorry, I hadn't noticed this. I'll edit my answer shortly – Valerio Cocchi Mar 10 '21 at 19:43
  • I think the issue is with the way WikiData's label service works. – Valerio Cocchi Mar 10 '21 at 19:50
  • Thanks.. I tried around a bit with your code and found that if I add "?birthplace rdfs:label ?birthplaceLabel ." in the SERVICE section I almost get what I want.. The only thing that I cant get out with this is the itemDescription – Mårten Swärd Mar 10 '21 at 19:52
0

Found the solution with a bit of modyfing of Valerio Cocchis answer.

SELECT ?item ?itemLabel ?itemDescription 
(SAMPLE(?birthplaceLabel) AS ?birthplaceLabel)
(SAMPLE(?birthdate) AS ?birthdate)
(SAMPLE(?deathplaceLabel) AS ?deathplaceLabel)
(SAMPLE(?deathdate) AS ?deathdate)
(SAMPLE(?imageLabel) AS ?imageLabel)
?article ?articleEn

WHERE {
  ?item wdt:P31 wd:Q5.
  ?item wdt:P119 wd:Q5024152.
  
  OPTIONAL {
    ?item wdt:P18 ?image.       
  }
  OPTIONAL {
    ?item wdt:P19 ?birthplace.
  }
  OPTIONAL {
    ?item wdt:P569 ?birthdate.    
  }
  OPTIONAL {
    ?item wdt:P20 ?deathplace.    
  }
  OPTIONAL {
    ?item wdt:P570 ?deathdate.
  }
  OPTIONAL {
     ?article schema:about ?item.
     ?article schema:isPartOf <https://sv.wikipedia.org/>.
  }
   OPTIONAL {
     ?articleEn schema:about ?item.
     ?articleEn schema:isPartOf <https://en.wikipedia.org/>.
  }
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "sv,en, [AUTO_LANGUAGE]". 
    ?birthplace rdfs:label ?birthplaceLabel . 
    ?deathplace rdfs:label ?deathplaceLabel .
    ?image rdfs:label ?imageLabel .
    ?item rdfs:label ?itemLabel .
    ?item schema:description ?itemDescription .
  }
}
GROUP BY ?item ?itemLabel ?itemDescription ?article ?articleEn