我正在尝试选择出生日期 ( 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 }
}
它可能可以使用 -> OPTIONAL(FILTER(BIND(IF(BOUND())))).. 但我无法弄清楚。
最佳答案
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
参数的作用是“初始化”A.K.A. 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)
。
it's more like this
如果这些属性中的任何一个匹配,则 ?ocpatoins
也将被绑定(bind)。
将属性分组为 VALUES
可以使查询更加高效,并且超时的可能性更小。
由于任何实际原因,MINUS
和 FILTER NOT EXISTS
都可以被认为是相同的。 (它们不属于边缘情况)
他们都会查看当前的匹配(在执行时)是否包含任何列出的属性“wd:P570,wd:P58,..”。但与 VALUES
不同的是,求值上下文是 |
OR,而不是 ANY。
我同时使用了 MINU
和 FILTER NOT EXISTS
,因为仅使用其中之一就会导致查询超时。
(它可能会变得更加高效,因为“wdt:102”迄今为止生成最多的匹配项,为后续运算符进行排序留下了太大的 block )
关于SPARQL - 如何过滤属性是否存在,否则按原样添加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59932176/