获取所有行,即使节点不总是存在

时间:2017-01-27 08:33:59

标签: xml tsql cross-apply

我有数以千计的xml文件来获取数据。 为了达到这个目的,我使用了交叉应用方法。

但问题是,某些节点并不总是出现在xml文件中。 在我的示例中,这是节点'valueX'(在产品节点内)。并且此节点仅出现在最后一个人中。

 <invoice>
    <person>
        <name>John</name>
        <product>
            <id>abc</id>
            <price>100</price>

        </product>
        <product>
            <id>def</id>
            <price>99</price>

        </product>
    </person>

    <person>
        <name>Mary</name>
        <product>
            <id>abc</id>
            <price>200</price>

        </product>
    </person>

    <person>
        <name>Peter</name>
        <product>
            <id>abc</id>
            <price>300</price>

        </product>
    </person>

    <person>
        <name>Sue</name>
        <product>
            <id>abc</id>
            <price>400</price>
            <valueX>
                <name>test</name>
            </valueX>
        </product>
    </person>

</invoice>

如果我现在使用'valueX'节点通过交叉应用查询xml文件,我只得到包含该节点的一条记录。

declare @tab table  (
                          id int
                        , xmlData xml
                    )

declare @xml nvarchar(max)

set @xml = '
                <invoice>
                    <person>
                        <name>John</name>
                        <product>
                            <id>abc</id>
                            <price>100</price>

                        </product>
                        <product>
                            <id>def</id>
                            <price>99</price>

                        </product>
                    </person>

                    <person>
                        <name>Mary</name>
                        <product>
                            <id>abc</id>
                            <price>200</price>

                        </product>
                    </person>

                    <person>
                        <name>Peter</name>
                        <product>
                            <id>abc</id>
                            <price>300</price>

                        </product>
                    </person>

                    <person>
                        <name>Sue</name>
                        <product>
                            <id>abc</id>
                            <price>400</price>
                            <valueX>
                                <name>test</name>
                            </valueX>
                        </product>
                    </person>

                </invoice>
            '


insert into @tab (id, xmlData)
values  (
              1
            , @xml
        )


select    t.id
        , Person.ref.value('name[1]','nvarchar(255)')   as PersonName
        , Product.ref.value('id[1]','nvarchar(3)')      as ProductID
        , Product.ref.value('price[1]','int')           as ProductPrice
        , ValueX.ref.value('name[1]','nvarchar(255)')   as ValueXName

from @tab as t

cross apply t.xmlData.nodes('invoice/person') Person(ref)
    cross apply Person.ref.nodes('product') Product(ref)
        cross apply Product.ref.nodes('valueX') ValueX(ref)    

但即使节点不存在,我也需要拥有所有记录。

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

只需将您的上一部分更改为

即可
from @tab as t

outer apply t.xmlData.nodes('invoice/person') Person(ref)
    outer apply Person.ref.nodes('product') Product(ref)
        outer apply Product.ref.nodes('valueX') ValueX(ref)   

CROSS APPLYINNER JOIN类似OUTER APPLY就像LEFT JOIN