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

Get all rows, even when node is not always present

我有数千个 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)    

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

我怎样才能做到这一点?

把你的最后一部分改成

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 APPLY 类似于 INNER JOINOUTER APPLY 类似于 LEFT JOIN