You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SPARQL实现Wikidata艺术品单一流派/材质查询?

SPARQL查询Wikidata:避免艺术品多流派/材质导致的重复行问题

需求背景

要查询1870年之后创作的艺术品,获取艺术品本体、图片、创作时间、创作者标签、艺术流派标签、材质标签。但一件艺术品可能关联多个流派或使用多种材质,导致查询结果出现重复行。希望每个艺术品仅返回一组(任意一个)流派/材质,无需手动去重,此前尝试用COUNT+HAVING限制结果但出现超时问题。

原查询语句

SELECT DISTINCT ?artwork ?image ?time ?creatorLabel ?movementLabel ?materialLabel WHERE {
  
  ?artwork wdt:P31 wd:Q3305213 ;
           wdt:P571 ?time ;
           wdt:P18 ?image .
  
OPTIONAL {
    ?artwork wdt:P170 ?creator 
    }
OPTIONAL {
    ?artwork wdt:P135 ?movement.
    }

OPTIONAL {
    ?artwork wdt:P186 ?material.
    }  

FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)

SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". } # 获取对应语言标签,无则用英文
  
}

LIMIT 100

可行解决方案

方法1:使用SAMPLE()聚合函数(推荐,性能优)

SAMPLE()会从多值结果中随机选取一个值,配合GROUP BY对每个艺术品分组,确保每个艺术品仅返回一行结果。这种方式无需遍历所有多值计数,性能远优于COUNT+HAVING,不会触发超时。

修改后的查询语句:

SELECT ?artwork ?image ?time ?creatorLabel (SAMPLE(?movementLabel) AS ?movementSample) (SAMPLE(?materialLabel) AS ?materialSample) WHERE {
  
  ?artwork wdt:P31 wd:Q3305213 ;
           wdt:P571 ?time ;
           wdt:P18 ?image .
  
OPTIONAL {
    ?artwork wdt:P170 ?creator 
    }
OPTIONAL {
    ?artwork wdt:P135 ?movement.
    }

OPTIONAL {
    ?artwork wdt:P186 ?material.
    }  

FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)

SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
  
}
GROUP BY ?artwork ?image ?time ?creatorLabel
LIMIT 100
  • 说明:GROUP BY指定所有需要保持唯一的字段(艺术品本体、图片、时间、创作者标签),SAMPLE()分别为流派和材质选取任意一个标签。

方法2:筛选仅含单个流派/材质的艺术品

如果需求是只返回确实只有一个流派或一种材质的艺术品(而非任意取一个),可以用EXISTS+NOT EXISTS进行存在性检查,这种方式比COUNT聚合更高效:

查询语句示例:

SELECT DISTINCT ?artwork ?image ?time ?creatorLabel ?movementLabel ?materialLabel WHERE {
  
  ?artwork wdt:P31 wd:Q3305213 ;
           wdt:P571 ?time ;
           wdt:P18 ?image .
  
OPTIONAL {
    ?artwork wdt:P170 ?creator 
    }
# 仅筛选只有一个流派的艺术品
OPTIONAL {
    ?artwork wdt:P135 ?movement.
    FILTER EXISTS {?artwork wdt:P135 ?m1}
    FILTER NOT EXISTS {?artwork wdt:P135 ?m2 FILTER (?m1 != ?m2)}
    }

# 仅筛选只有一种材质的艺术品
OPTIONAL {
    ?artwork wdt:P186 ?material.
    FILTER EXISTS {?artwork wdt:P186 ?mat1}
    FILTER NOT EXISTS {?artwork wdt:P186 ?mat2 FILTER (?mat1 != ?mat2)}
    }  

FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)

SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
  
}
LIMIT 100
  • 说明:通过NOT EXISTS排除存在多个不同流派/材质的艺术品,仅保留单值条目。

为什么COUNT+HAVING会超时?

Wikidata数据集规模极大,COUNT聚合需要遍历每个艺术品的所有关联流派/材质并计数,计算开销极高,容易触发查询超时。而上述两种方法要么仅选取单个值(SAMPLE()),要么通过存在性检查快速过滤(EXISTS),计算量远小于聚合计数。

内容的提问来源于stack exchange,提问作者K3it4r0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 14:12:06