SPARQL - Как отфильтровать, если свойство существует, в противном случае добавить как есть? - PullRequest
0 голосов
/ 27 января 2020

Я пытаюсь выбрать людей, чья дата рождения (wdt: P569) превышает 1920, если у них есть дата рождения, и добавить всех остальных, у которых нет даты рождения.

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 }

}

Вероятно, это можно решить с помощью -> ДОПОЛНИТЕЛЬНО (FILTER (BIND (IF (BOUND ())))) .. Но я не могу понять это.

1 Ответ

0 голосов
/ 31 января 2020
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 }

}

Спасибо, AKSW!

Работа параметра OPTIONAL заключается в том, чтобы "инициализировать" переменную AKA BIND.

FILTER( !BOUND(?date) || year(?date)>1920 ) говорит - добавить к результатам все совпадения, где переменная ?date не была "инициализирована" или если она была "инициализирована" - добавить все совпадения, где фильтр year(?date) > 1920 оценивается как true .

и пока я на нем:

VALUES ?occupations {wd:Q82955 wd:Q212238 wd:Q193391 wd:Q116} эквивалентно javascript высказыванию var x = (a || b || c || d). это больше похоже на Если какое-либо из этих свойств совпадает, то ?occupatoins также становится связанным. Группирование ваших свойств в VALUES делает запрос более эффективным и меньше шансов на его истечение.

MINUS и FILTER NOT EXISTS по любой практической причине можно считать идентичными. (они не в крайних случаях). Они оба смотрят, если соответствие (на данный момент выполнения) содержит любое из перечисленных свойств "wd: P570, wd: P58, ..". Но в отличие от VALUES контекст оценки - | ИЛИ, а не ЛЮБОЙ.

Я использовал MINU и FILTER NOT EXISTS, потому что использование только одного из них сократило время запроса.

(это могло бы стать более эффективным, потому что "wdt: 102" дает гораздо больше совпадений, оставляя слишком большой кусок для следующих операторов)

...