XQuery查询结果去重并返回关联字段值的实现问题
问题根因
你写的代码逻辑存在两个核心错误:
- 定义
$briefbio、$birth、$death三个变量时,直接拉取了文档内所有对应字段的全量值集合,没有和当前循环的唯一ID做绑定 - 遍历去重后的ID时,没有反向定位到该ID所属的完整Record节点,自然无法正确获取和ID匹配的其他关联字段,要么返回全量重复值,要么匹配错位
这个场景不需要调用fn:duplicate-values,用原生节点筛选逻辑就能实现去重需求。
可直接运行的实现代码
<report> { let $all-records := doc("People_list_test_edited.xml")/data/Details/Record for $unique-id in distinct-values($all-records/Field[@Name='GroupNameLINKID1']/FormattedValue) (: 只取当前ID匹配到的第一条记录,自动跳过后续重复的同ID条目 :) let $matched-record := $all-records[Field[@Name='GroupNameLINKID1']/FormattedValue = $unique-id][1] return <object> <id>{$unique-id}</id> <briefbio>{$matched-record/Field[@Name='BRIEFBIO1']/FormattedValue/data()}</briefbio> <birth>{$matched-record/Field[@Name='BIRTHDATE1']/FormattedValue/data()}</birth> <death>{$matched-record/Field[@Name='DEATHDATE1']/FormattedValue/data()}</death> </object> } </report>
逻辑说明
- 第一步先把所有Record节点存入
$all-records变量,避免多次重复扫描全文档 - 遍历去重后的ID时,通过方括号内的筛选条件,定位到和当前ID对应的Record节点,追加
[1]是为了仅返回第一条匹配结果,自动过滤后续重复的同ID记录 - 所有关联字段都从已经匹配到的单条
$matched-record节点中提取,不会出现值错位、重复输出的问题
如果你的重复判定规则不是仅靠GroupNameLINKID1字段,而是要求整条记录所有字段完全一致才算重复,可以直接对Record节点做深度去重,写法更简洁:
<report> { let $all-records := doc("People_list_test_edited.xml")/data/Details/Record (: 对整条记录做序列化后去重,适配全字段重复场景 :) for $unique-record in distinct-values($all-records ! serialize(.)) ! parse-xml(.) return <object> <id>{$unique-record/Field[@Name='GroupNameLINKID1']/FormattedValue/data()}</id> <briefbio>{$unique-record/Field[@Name='BRIEFBIO1']/FormattedValue/data()}</briefbio> <birth>{$unique-record/Field[@Name='BIRTHDATE1']/FormattedValue/data()}</birth> <death>{$unique-record/Field[@Name='DEATHDATE1']/FormattedValue/data()}</death> </object> } </report>
注意:全字段深度去重的写法依赖XQuery 3.0及以上版本支持,如果你的运行环境是XQuery 1.0,使用前文中按ID匹配的写法即可。
内容的提问来源于stack exchange,提问作者IIAND
相关产品推荐
相关产品推荐

