I'm trying to query data from species' pages on Wikidata with the following query :
SELECT ?animal ?animalLabel ?iucncode ?photo WHERE {
VALUES ?iucncode { "714" }
?animal wdt:P627 ?iucncode
OPTIONAL {
?animal wdt:P18 ?photo.
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
I'm changing the value of ?iucncode
to get data about different species. With the current query I get as many results as there are images, for a single page. I would like to have a response with a single line for each page, with 3 columns of data for the first 3 images (if available). Is there a way to do that with SPARQL ?
For the species in the example above, instead of having 4 lines with these columns :
animal | animalLabel | iucncode | photo |
---|
I would like to have a single line like so :
animal | animalLabel | iucncode | photo_1 | photo_2 | photo_3 |
---|
Here is one way to do it:
SELECT
?animal ?animalLabel ?iucncode
(SAMPLE(?photo1) as ?photo1)
(SAMPLE(?photo2) as ?photo2)
(SAMPLE(?photo3) as ?photo3)
WHERE {
VALUES ?iucncode { "714" "6736" "550" "899" }
?animal wdt:P627 ?iucncode
OPTIONAL {
?animal wdt:P18 ?photo1.
}
BIND(IF( BOUND( ?photo1), ?photo1,"NA1") AS ?photo1)
OPTIONAL {
?animal wdt:P18 ?photo2.
FILTER ( ?photo1 != ?photo2)
}
BIND(IF( BOUND( ?photo2), ?photo2,"NA2") AS ?photo2)
OPTIONAL {
?animal wdt:P18 ?photo3.
FILTER ( ?photo1 != ?photo3)
FILTER ( ?photo2 != ?photo3)
}
BIND(IF( BOUND( ?photo3), ?photo3,"NA3") AS ?photo3)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?animal ?animalLabel ?iucncode
You can also see it on the WDQS: https://w.wiki/3WUi
OPTIONAL + FILTER (?A != ?B)
for getting distinct photo on each variableBIND(IF( BOUND( ?a), ?a,"NA") AS ?a)
for making sure there is some result returned for each variable, even if there was no match on Wikidata?a (SAMPLE (?b) as ?b) (SAMPLE (?c) as ?c) + GROUP BY ?a
to get single results and eliminate duplicatesThere might be smarter ways to solve it, though.