Wikidata SPARQL returns 结果太多
Wikidata SPARQL returns too many results
这是可以在 https://query.wikidata.org 中执行的查询,我应该只得到 17 个值,但它 returns 有 289 个结果 (17 * 17 = 289)。
我想用它的单位得到 属性 值。我指定 wdt:P2573
只是为了演示这个问题,在实际应用中 属性 是一个变量 ?p
.
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT * WHERE {
wd:Q2 wdt:P2573 ?o.
wd:Q2 rdfs:label ?entName.
?realAtt wikibase:directClaim wdt:P2573.
?realAtt rdfs:label ?attName.
?realAtt wikibase:propertyType ?wdDataType.
OPTIONAL {
?realAtt wikibase:statementValue ?psv.
?realAtt wikibase:claim ?pp.
wd:Q2 ?pp ?quantityNode.
?quantityNode ?psv ?wdv.
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
BIND(?qAmount AS ?val)
}
BIND(COALESCE(?val, ?o) AS ?val)
BIND(COALESCE(?unit, "") AS ?unit)
FILTER(((LANG(?o)) = "en") || ((LANG(?o)) = "") || (!ISLITERAL(?o)))
FILTER(((LANG(?attName)) = "en") || ((LANG(?attName)) = ""))
FILTER(((LANG(?entName)) = "en") || ((LANG(?entName)) = ""))
}
真实陈述的简单值不会与值节点自动连接(class diagram).
您的 MCVE 应该如下所示:
SELECT * WHERE {
wd:Q2 wdt:P2573 ?o.
OPTIONAL {
wd:Q2 p:P2573/psv:P2573 ?wdv.
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
# FILTER( ?unit != wd:Q199 )
}
}
在上面的查询中,?o
和 ?wdv
的唯一连接条件是它们与 wd:Q2
的相关性。
因此,您获得了 ?o
和 ?wdv
绑定的笛卡尔积(右,17×17 = 289)。
正确的查询应该是这样的:
SELECT * WHERE {
wd:Q2 p:P2573/psv:P2573 ?wdv.
OPTIONAL {
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
}
}
更新
以上查询仅适用于 quantities。显然,它不适用于时间或地球坐标。此外,有时语句根本没有完整的值。例如,带有字符串对象的语句只有简单的值。应该从语句中获取简单值,然后尝试从完整值中获取附加信息:
SELECT * {
VALUES (?wd) {(wd:P2067)(wd:P1332)(wd:P1814)}
?wd wikibase:claim ?p;
wikibase:statementProperty ?ps;
wikibase:statementValue ?psv.
wd:Q2 ?p ?wds.
?wds ?ps ?sv.
OPTIONAL {
?wds ?psv ?wdv
OPTIONAL {?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?amount}
}
}
总的来说,语句的特征可以是多种多样的。用 table 格式表示所有这些数据不是很方便。这就是 RDF 存在的原因之一。
这是可以在 https://query.wikidata.org 中执行的查询,我应该只得到 17 个值,但它 returns 有 289 个结果 (17 * 17 = 289)。
我想用它的单位得到 属性 值。我指定 wdt:P2573
只是为了演示这个问题,在实际应用中 属性 是一个变量 ?p
.
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT * WHERE {
wd:Q2 wdt:P2573 ?o.
wd:Q2 rdfs:label ?entName.
?realAtt wikibase:directClaim wdt:P2573.
?realAtt rdfs:label ?attName.
?realAtt wikibase:propertyType ?wdDataType.
OPTIONAL {
?realAtt wikibase:statementValue ?psv.
?realAtt wikibase:claim ?pp.
wd:Q2 ?pp ?quantityNode.
?quantityNode ?psv ?wdv.
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
BIND(?qAmount AS ?val)
}
BIND(COALESCE(?val, ?o) AS ?val)
BIND(COALESCE(?unit, "") AS ?unit)
FILTER(((LANG(?o)) = "en") || ((LANG(?o)) = "") || (!ISLITERAL(?o)))
FILTER(((LANG(?attName)) = "en") || ((LANG(?attName)) = ""))
FILTER(((LANG(?entName)) = "en") || ((LANG(?entName)) = ""))
}
真实陈述的简单值不会与值节点自动连接(class diagram).
您的 MCVE 应该如下所示:
SELECT * WHERE {
wd:Q2 wdt:P2573 ?o.
OPTIONAL {
wd:Q2 p:P2573/psv:P2573 ?wdv.
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
# FILTER( ?unit != wd:Q199 )
}
}
在上面的查询中,?o
和 ?wdv
的唯一连接条件是它们与 wd:Q2
的相关性。
因此,您获得了 ?o
和 ?wdv
绑定的笛卡尔积(右,17×17 = 289)。
正确的查询应该是这样的:
SELECT * WHERE {
wd:Q2 p:P2573/psv:P2573 ?wdv.
OPTIONAL {
?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?qAmount.
}
}
更新
以上查询仅适用于 quantities。显然,它不适用于时间或地球坐标。此外,有时语句根本没有完整的值。例如,带有字符串对象的语句只有简单的值。应该从语句中获取简单值,然后尝试从完整值中获取附加信息:
SELECT * {
VALUES (?wd) {(wd:P2067)(wd:P1332)(wd:P1814)}
?wd wikibase:claim ?p;
wikibase:statementProperty ?ps;
wikibase:statementValue ?psv.
wd:Q2 ?p ?wds.
?wds ?ps ?sv.
OPTIONAL {
?wds ?psv ?wdv
OPTIONAL {?wdv wikibase:quantityUnit ?unit.
?wdv wikibase:quantityAmount ?amount}
}
}
总的来说,语句的特征可以是多种多样的。用 table 格式表示所有这些数据不是很方便。这就是 RDF 存在的原因之一。