这些标签连接/合并是否可以在 Sparql 中高效地进行?

问题描述 投票:0回答:1

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;

但我真正想要的是通过两种方式合并重复项:

  1. 如果标签与英文标签相同,无需告诉我。
  2. 告诉我所有其他内容,并在标签上附上语言代码列表。

所以像这样:

日本@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:
更快?

sparql wikidata
1个回答
0
投票

(以 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 种语言。

© www.soinside.com 2019 - 2024. All rights reserved.