Jay
Jay

Reputation: 127

Prioritizing attribute in Sparql query

This is a question about Sparql and Wikidata. I want to formulate a query that returns an instance-type relation, but if it's not available return its sub-class. I tried:

SELECT DISTINCT  ?ent_type  WHERE { 

 { wd:Q7696957 wdt:P31 ?instanceof . } UNION 
 { wd:Q7696957 wdt:P31/wdt:P279? ?subclass .  } UNION 
 { wd:Q7696957 wdt:P279* ?subclass  . } 

 BIND ( IF (BOUND (?instanceof), ?instanceof, ?subclass ) as ?ent_type  ) 

But unfortunately this returns all solutions, whereas I only want one solution

ent_type
----------
wd:Q811979
wd:Q386724
wd:Q811430
wd:Q7696957

Upvotes: 2

Views: 143

Answers (2)

evsheino
evsheino

Reputation: 2277

To simplify Joshua's answer, you don't actually need the coalesce:

select distinct ?ent_type where { 
  optional { wd:Q7696957 wdt:P31 ?ent_typee . }
  optional { wd:Q7696957 wdt:P31/wdt:P279? ?ent_type . }
  optional { wd:Q7696957 wdt:P279* ?ent_type . }
}

If there are multiple optionals with the same variable name (here ?ent_type), the first "successful" one will bind the variable.

However, there seems to be a problem with your query logic: if there is no value for wdt:P31, then neither is there for wdt:P31/wdt:P279?, so there will never be a situation where the middle condition is met. Also, wdt:P279* will (because of the *) return the resource itself (wd:Q7696957) if there is no value for wdt:P279 (which may or may not be what you want).

Upvotes: 2

Joshua Taylor
Joshua Taylor

Reputation: 85823

You can use coalesce to achieve this:

select distinct ?ent_type where { 
  optional { wd:Q7696957 wdt:P31 ?direct }
  optional { wd:Q7696957 wdt:P31/wdt:P279? ?indirect }
  optional { wd:Q7696957 wdt:P279* ?ancestor }
  bind(coalesce(?direct, ?indirect, ?ancestor) as ?ent_type)
}

Upvotes: 5

Related Questions