Nils Riga
Nils Riga

Reputation: 110

SPARQL - How to Filter if a property exists, otherwise add as is?

I am trying to select people, whose date of birth ( wdt:P569 ) is above 1920, if they have a date of birth and add everybody else who don't have a date of birth.

SELECT ?politician
WHERE {

VALUES ?occupations {wd:Q193391 wd:Q116}

?politician wdt:P106  ?occupations .
OPTIONAL {
  ?politician wdt:P569 ?date .
  FILTER (year(?date) > 1920)
}

MINUS {?politician wdt:P102 ?o }
FILTER NOT EXISTS {?politician wdt:P570|wdt:P509|wdt:P20 ?o }

}

It probably can be solved using -> OPTIONAL(FILTER(BIND(IF(BOUND())))).. But I can't figure it out.

Upvotes: 2

Views: 6798

Answers (1)

Nils Riga
Nils Riga

Reputation: 110

SELECT ?politician
WHERE {

VALUES ?occupations {wd:Q82955 wd:Q212238 wd:Q193391 wd:Q116}

?politician wdt:P106  ?occupations .
OPTIONAL {?politician wdt:P569 ?date .}
  FILTER (!bound(?date) || year(?date) > 1920) 

MINUS {?politician wdt:P102 ?o }
FILTER NOT EXISTS {?politician wdt:P570|wdt:P509|wdt:P20 ?o }

}

Thank you AKSW!

the OPTIONAL parameter's job is to "initialize" A.K.A. BIND a variable.

The FILTER( !BOUND(?date) || year(?date)>1920 ) is saying - add to results all the matches, where ?date variable was not "initialized" or if it was "initialized" - add all the matches where year(?date) > 1920 filter evaluates to true.

and while I'm on it:

VALUES ?occupations {wd:Q82955 wd:Q212238 wd:Q193391 wd:Q116} is javascript's equivalent of saying var x = (a || b || c || d). it's more like this If any of those properties match, then ?occupatoins becomes bound as well. Grouping your properties into VALUES makes the query more efficient and there's less of a chance it will time out.

The MINUS and FILTER NOT EXISTS for any practical reason can be considered identical. (they are not in edge cases) Both of them look, if the match at hand (at that point of the execution) contain any of the listed properties "wd:P570, wd:P58, ..". But unlike VALUES the evaluation context is | OR, not of ANY.

I used both MINU and FILTER NOT EXISTS because using just one of them made the query time out.

(it might have become more efficient, because "wdt:102" produces by far the most matches, leaving too big of a chunk for the following operators to sort through)

Upvotes: 4

Related Questions