从https://stackoverflow.com/a/57856942/841830中显示的示例开始然后我将它们分组为每个国家/地区只有一行。 (21600 毫秒内有 208 个结果;原来的 19484 毫秒内有 53,546 个结果,所以它并没有减慢太多。)
SELECT ?country (GROUP_CONCAT(?label; SEPARATOR=";") AS ?labels) (GROUP_CONCAT(lang(?label); SEPARATOR=";") as ?label_langs) ?countryLabel
WHERE
{
?country wdt:P31 wd:Q6256.
?country rdfs:label ?label .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?country ?countryLabel
请注意,我不能使用
DISTINCT
,因为标签会被合并,但语言代码不会,因此它们将不再处于 1-1 关系。
举个例子,这是我在日本得到的(第 17 季度)的精简版(前 16 个标签):
日本;Japan;Japó;ژاپن;Japan;Japan;Giappone;ಜಪಾನ್;Japon;Япония;Japan;Hapon;Hapon;Japonia;Japón;Japan;
ja;nl;ca;fa;en;de;it;kn;fr;ru;en-gb;ilo;tl;ro;es;din
将语言代码直接附加到每个标签会很好,所以我只有一个字符串。所以它看起来像:
日本@ja;Japan@nl;Japó@ca;ژاپن@fa;Japan@en;Japan@de;Giappone@it;ಜಪಾನ್@kn;Japon@fr;Япония@ry;Japan@en-gb;Hapon@ilo;Hapon@tl;Japonia@ro;Japón@es;Japan@din;
但我真正想要的是通过两种方式合并重复项:
所以像这样:
日本@ja;Japó@ca;ژاپن@fa;Giappone@it;ಜಪಾನ್@kn;Japon@fr;Япония@ry;Hapon@ilo,tl;Japonia@ro;Japón@es;
(删除所有“Japan”实例,并合并
ilo
和 tl
。)
当然,我可以在导出后在后处理脚本中完成所有这些操作。 但我想知道在不增加查询时间的情况下,我们可以在 SPARQL 中走多远?
旁白:如果我将
?country rdfs:label ?label .
更改为 ?country skos:altLabel ?label .
它在 7151 毫秒内返回 203 个结果。原始链接查询在 7776 毫秒内减少到 20,258 个结果。由于字符串总数是原始字符串的 40%,这两种情况下是否运行得更快?或者 skos:
根本上比 rdfs:
更快?
(以 UninformedUser 的评论为起点。)
首先,要获得单列,请将国家/地区名称和语言代码组合在一起,简单如下:
(GROUP_CONCAT(CONCAT(?label, "@", lang(?label)); SEPARATOR=";") AS ?labels)
顺便说一句,在尝试查询时,一个不错的提示是将
BIND(wd:Q17 AS ?country)
作为 WHERE{...}
中的第一行,这样只需获取一个国家/地区(本例中为日本)即可使其运行速度更快。
要从
?labels
中提取英文标签,我们将 SERVICE wikibase:label
行替换为 ?country rdfs:label ?en_label
,然后是所需语言的过滤器。
SELECT ?country ?en_label (GROUP_CONCAT(CONCAT(?label, "@", lang(?label)); SEPARATOR=";") AS ?labels)
WHERE
{
?country wdt:P31 wd:Q6256.
?country rdfs:label ?label .
?country rdfs:label ?en_label . FILTER(lang(?en_label) = "en")
# FILTER(str(?label) != str(?en_label))
}
GROUP BY ?country ?en_label
然后要排除使用英文标签作为国家/地区名称的国家/地区,请取消注释
FILTER(str(?label) != str(?en_label))
行。
在我的测试中,之前需要 56 秒,并且过滤器超时。在一个国家/地区进行测试时,添加过滤器似乎会使查询时间增加一倍,所以这是有道理的。
UninformedUser 的查询在 2.6 秒内运行,并且似乎给出了相同的结果:
SELECT ?country ?en_label (GROUP_CONCAT(CONCAT(?label, "@", lang(?label)); SEPARATOR=";") as ?other_labels)
WHERE {
{
SELECT * {
# BIND(wd:Q17 AS ?country)
?country wdt:P31 wd:Q6256.
?country rdfs:label ?en_label .
FILTER(lang(?en_label) = "en")
hint:SubQuery hint:runOnce true .
}
}
hint:Prior hint:runFirst true .
?country rdfs:label ?label .
FILTER(str(?label) != str(?en_label))
}
GROUP BY ?country ?en_label
我假设嵌套的
SELECT * {...}
被用来能够给出两个 hint
。在这个阶段,我不知道是否是嵌套 SELECT、hint:SubQuery
或 hint:Prior
在运行时造成如此大的差异。
https://www.wikidata.org/wiki/Wikidata:SPARQL_query_service/query_optimization也许可以解释它。
鉴于迄今为止缺乏答案,当标签相同时,似乎无法连接国家/地区代码。例如。对于日本,“Japon”用于法语和其他 15 种语言,“Япония”用于俄语和其他 9 种语言。