含UNION的SPARQL查询去重:仅保留有值的孪生实体结果
解决WDQS孪生实体查询的重复与超时问题
问题拆解
你的查询用UNION合并了两类孪生实体:
- 标记为「孪生」类(wd:Q159979)的实体
- 通过同生日+亲生母亲关联找到的有孪生兄弟姐妹的实体
但同时满足两类条件的实体会重复输出(比如丹麦约瑟芬公主),一条带具体孪生信息(?twin_2_name/?twin_2_desc),一条不带。你要的是优先保留有孪生信息的条目,只有当没有孪生信息时才显示缺失值,之前试了COALESCE没用还超时。
优化后的查询方案
核心逻辑是先抓取有明确孪生对象的条目,再补全那些找不到孪生对象但属于「孪生」类的实体,同时优化查询逻辑减少计算量:
SELECT ?twin_name ?twin_desc ?date_birth ?twin_2_name ?twin_2_desc WHERE { # 第一部分:优先获取有明确孪生兄弟姐妹的实体 { ?twin p:P569 ?p569 . ?p569 wikibase:rank wikibase:BestRank ; psv:P569 ?psv569 . ?psv569 wikibase:timePrecision ?time_precision ; wikibase:timeValue ?date_birth . FILTER (?time_precision >= 11) # 匹配亲生母亲的两种方式 { ?twin wdt:P25 ?mother } UNION { ?twin ^wdt:P40 ?mother . ?mother wdt:P21 wd:Q6581072 } ?mother wdt:P40 ?twin_2 . FILTER (?twin != ?twin_2) ?twin_2 wdt:P569 ?date_birth . # 孪生对象的英文名称和描述 ?twin_2 rdfs:label ?twin_2_name . FILTER (lang(?twin_2_name) = "en") ?twin_2 schema:description ?twin_2_desc . FILTER (lang(?twin_2_desc) = "en") } UNION # 第二部分:仅补充那些找不到孪生对象,但属于「孪生」类的实体 { ?twin wdt:P31/(wdt:P279)* wd:Q159979 . ?twin wdt:P569 ?date_birth . # 排除已经在第一部分匹配到的实体,避免重复 FILTER NOT EXISTS { ?twin p:P569 ?p569 . ?p569 wikibase:rank wikibase:BestRank ; psv:P569 ?psv569 . ?psv569 wikibase:timePrecision ?time_precision ; wikibase:timeValue ?date_birth . FILTER (?time_precision >= 11) { ?twin wdt:P25 ?mother } UNION { ?twin ^wdt:P40 ?mother . ?mother wdt:P21 wd:Q6581072 } ?mother wdt:P40 ?twin_2 . FILTER (?twin != ?twin_2) ?twin_2 wdt:P569 ?date_birth . } # 无孪生信息时显示占位符,不需要的话可以删掉这两行 BIND("-" AS ?twin_2_name) BIND("-" AS ?twin_2_desc) } # 主实体的英文名称和描述 ?twin rdfs:label ?twin_name . FILTER (lang(?twin_name) = "en") ?twin schema:description ?twin_desc . FILTER (lang(?twin_desc) = "en") # 按站点链接数排序(保留原逻辑,嫌慢可以删掉) ?twin ^schema:about/wikibase:sitelinks ?sitelinks . } ORDER BY DESC(?sitelinks)
关键改进点
- 去重逻辑:用
FILTER NOT EXISTS确保第二部分只补充第一部分没覆盖到的实体,彻底避免重复 - 性能优化:
- 删掉原查询的
DISTINCT,减少不必要的去重计算 - 修正了原查询中
rdf:type wikibase:BestRank的错误,应该用wikibase:rank wikibase:BestRank来指定最佳排名的声明 - 把重复的匹配逻辑放到
FILTER NOT EXISTS里,避免重复遍历数据
- 删掉原查询的
- 需求匹配:完全实现你要的「有孪生信息就留,没有才显示缺失」的逻辑
额外提示
- 如果不想显示
-占位符,直接删掉那两行BIND,缺失字段会为空 - 如果还是超时,建议去掉
sitelinks相关的排序(这个字段需要统计每个实体的站点链接数,计算量很大),或者加LIMIT限制返回条数
内容的提问来源于stack exchange,提问作者xhgf5
相关产品推荐
相关产品推荐

