了解XQuery中的联接

时间:2015-08-03 22:51:22

标签: xml join xquery

我想要使用XQuery加入两个XML文档。我知道数据包含一些重复的条目。

test1.xml

<marc:collection
    xmlns:marc="http://www.loc.gov/MARC21/slim">
    <marc:record>
        <marc:leader>01225cam a2200373Mi 4500</marc:leader>
        <marc:controlfield tag="001">5323084</marc:controlfield>
        <marc:datafield
            ind1="1"
            ind2="4"
            tag="245">
            <marc:subfield code="a">Els teleclubs a les illes Balears :</marc:subfield>             
        </marc:datafield>
    </marc:record>
    <marc:record>
        <marc:leader>01225cam a2200373Mi 4500</marc:leader>
        <marc:controlfield tag="001">5323084</marc:controlfield>
        <marc:datafield
            ind1="1"
            ind2="4"
            tag="245">
            <marc:subfield code="a">Els teleclubs a les illes Balears :</marc:subfield>             
        </marc:datafield>
    </marc:record>
    <marc:record>
        <marc:leader>00818cam a2200241Mi 4500</marc:leader>
        <marc:controlfield tag="001">6310976</marc:controlfield>
        <marc:datafield
            ind1="0"
            ind2="0"
            tag="245">
            <marc:subfield code="a">Diccionari manual de sinònims i antònims de la llengua catalana /</marc:subfield>             
        </marc:datafield>
    </marc:record>
</marc:collection>

test2.xml

<root>
    <row>
        <LANGUAGE>cat</LANGUAGE>
        <ITEM_ID>5912416</ITEM_ID>
        <BIB_ID>5323084</BIB_ID>    
        <VENDOR_CODE>MXBKSMX</VENDOR_CODE>
    </row>
    <row>
        <LANGUAGE>cat</LANGUAGE>
        <ITEM_ID>5912416</ITEM_ID>
        <BIB_ID>5323084</BIB_ID>        
        <VENDOR_CODE>PUVILL</VENDOR_CODE>
    </row>
    <row>
        <LANGUAGE>cat</LANGUAGE>
        <ITEM_ID>5935043</ITEM_ID>
        <BIB_ID>6310976</BIB_ID>
        <VENDOR_CODE>PUVILL</VENDOR_CODE>
    </row>
</root>

我正在尝试使用来自marc:controlfield[@tag = '001']的{​​{1}}和来自test1.xml的{​​{1}}的值来进行简单的联接。

的XQuery

BIB_ID

当我运行这个时,我得到前两个匹配的重复值:

test2.xml

我可以通过添加xquery version "3.0"; declare namespace marc="http://www.loc.gov/MARC21/slim"; for $m in doc("test1.xml")/marc:collection/marc:record, $r in doc("test2.xml")/root/row[BIB_ID = $m/marc:controlfield[@tag = '001']] return <test n="{$r/ITEM_ID}">{ $m/marc:datafield[@tag = '245']/marc:subfield[@code = 'a']/string() }</test> 子句来解决这个问题:

<test n="5912416">Els teleclubs a les illes Balears :</test>
<test n="5912416">Els teleclubs a les illes Balears :</test>
<test n="5912416">Els teleclubs a les illes Balears :</test>
<test n="5912416">Els teleclubs a les illes Balears :</test>
<test n="5935043">Diccionari manual de sinònims i antònims de la llengua catalana /</test>

结果

group by

但是我想理解为什么在第一种情况下,为每个for $m in doc("test2.xml")/marc:collection/marc:record, $r in doc("test1.xml")/root/row[BIB_ID = $m/marc:controlfield[@tag = '001']] group by $key := $r/ITEM_ID return <test c="{$key}">{ $m/marc:datafield[@tag = '245']/marc:subfield[@code = 'a']/string() }</test> 子句重复重复的条目。为什么第二个<test c="5912416">Els teleclubs a les illes Balears : Els teleclubs a les illes Balears :</test> <test c="5935043">Diccionari manual de sinònims i antònims de la llengua catalana /</test 子句中的谓词不会在连接发生时过滤掉重复的值?如果我确实想要保留重复的条目(没有不必要的重复),那么最好的方法是什么?

2 个答案:

答案 0 :(得分:2)

许多XPath XQuery表达式消除了重复节点,因为同一节点在结果中没有出现两次,但是没有表达式可以消除重复项,因为节点是深度相等的(所有子节点,后代和属性相同)。

我对这个问题的直觉是在进行连接之前消除输入中的重复,而不是从结果中消除它们。

  

&#34;如果我确实想保留重复的条目(没有   什么是最好的方法?#34;

根据我的经验,在这种情况下,你通常会想要一个树形结构,而不是一个平坦的结果,所以你必须抛出关系思维。你通常会得到类似

的表达式
for $i in $input return
<parent value="{$i/something}">{
  for $j in $anotherInput[$j/xyz = $i/abc] return
    <child value="{$j/something}"> {
      f($i, $j)
    }</child>
}</parent>

答案 1 :(得分:1)

这是预期的行为,在SQL JOIN中可以观察到类似的效果。当用于JOIN的密钥不是唯一的时,您将获得具有匹配密钥的所有数据的笛卡儿产品

例如,在这种情况下,第一个XML中有2个<row>元素BIB_ID等于5323084,并且有2个<marc:record>个元素与第二个XML。因此,当将2行数据与另外2行数据配对时,结果是所有可能的组合(参见图示*),这导致4种可能的组合(2 x 2),如您在XQuery结果中观察到的那样。

enter image description here

*:该图实际用于说明source article中的CROSS JOIN,但效果相同。