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

Wikidata SPARQL如何实现单值取原值多值取指定限定词值

问题

是否可以在Wikidata SPARQL中实现如下逻辑:

# 伪代码
if 某属性仅有1个值:
    直接返回该值
else:
    返回带子属性x限定的值
背景与现有尝试

需求场景为通过Wikidata获取瑞典议会议员的given name,用于选举相关数据可视化,目标是为每位议员返回单个given name:

  • 单名示例:人物条目下P735(given name)属性仅挂载1个名字值,无额外角色标记
  • 多名示例:人物条目下P735属性挂载3个名字,其中1个名字携带object has role属性,属性值为usual first name(常用名),其余名字无该标记

现有两段查询均无法满足需求:

  • 直接查询P735属性的版本会为每个given name返回一行结果,多名字人物会返回多行重复的人物记录:
SELECT ?personLabel ?givenNamesLabel
WHERE {
  ?person wdt:P39 wd:Q10655178 . # 匹配担任瑞典议会议员职位的人物
  ?person wdt:P735 ?givenNames . # 匹配人物的所有given name
  
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". 
  }
}
  • 仅筛选带usual first name角色标记名字的版本,会遗漏只有单个given name、无角色标记的人物:
SELECT ?personLabel ?givenNameSingularLabel
WHERE {
  ?person wdt:P39 wd:Q10655178 . # 匹配担任瑞典议会议员职位的人物
  
  ?person p:P735 ?givenNames .             # 定位P735属性的声明节点
  ?givenNames ps:P735 ?givenNameSingular . # 取声明对应的given name值
  ?givenNames pq:P3831 wd:Q3409033 .       # 筛选声明带"常用名"角色限定
  
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". 
  }
}
实现方案

可以通过计数聚合+优先级匹配的逻辑实现需求,核心思路:

  • 先统计每个人物挂载的given name总数
  • 为两类名字分配优先级:带usual first name标记的名字优先级为1,无标记的普通名字优先级为2
  • 单名人物直接返回唯一的名字值,多名人物优先返回带常用名标记的值
  • 可按需增加兜底逻辑,覆盖多名人物未标注常用名的边缘场景,确保无空值

可直接运行的基础版本查询代码如下:

SELECT ?personLabel ?finalGivenNameLabel
WHERE {
  # 匹配所有瑞典议会议员
  ?person wdt:P39 wd:Q10655178 .
  
  # 统计每个人物的given name总数
  {
    SELECT ?person (COUNT(?allGiven) AS ?givenNameCount)
    WHERE {
      ?person wdt:P735 ?allGiven .
    }
    GROUP BY ?person
  }
  
  # 匹配所有given name,计算优先级
  ?person p:P735 ?nameStmt .
  ?nameStmt ps:P735 ?finalGivenName .
  OPTIONAL { ?nameStmt pq:P3831 wd:Q3409033 . BIND(1 AS ?priority) }
  BIND(COALESCE(?priority, 2) AS ?namePriority)
  
  # 按规则筛选符合要求的名字
  FILTER(
    ?givenNameCount = 1
    ||
    (?givenNameCount > 1 && ?namePriority = 1)
  )
  
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE],sv,en". 
  }
}

若需要覆盖「多名字但未标注常用名」的边缘场景,可将上述筛选逻辑替换为按人物分组取最高优先级名字的逻辑,确保每个人物一定返回1个结果,调整后的核心逻辑段如下:

# 替换原代码中的优先级匹配+筛选段
{
  SELECT ?person ?finalGivenName (MIN(?namePriority) AS ?topPriority)
  WHERE {
    ?person p:P735 ?nameStmt .
    ?nameStmt ps:P735 ?finalGivenName .
    OPTIONAL { ?nameStmt pq:P3831 wd:Q3409033 . BIND(1 AS ?priority) }
    BIND(COALESCE(?priority, 2) AS ?namePriority)
  }
  GROUP BY ?person ?finalGivenName
}
FILTER(?namePriority = ?topPriority)

内容的提问来源于stack exchange,提问作者David Van Dorsten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:15:31