SQL 服务器中的 Xquery

Xquery in SQL Server

我正在尝试为此处显示的 XML 解析我的 XML 元素。我需要层次结构中的不同元素。

我需要 E1EDKA1E1EDK02 的所有重复元素的一些属性。

如果我将我的 XPath 设置为

@XML.nodes('//*:ZINVOIC2/*:IDOC/*:E1EDKA1')

我能够访问 E1EDKA1E1EDK01 的元素。但是我有多个E1EDK02.QUALF的元素。如何在单独的行中获取 E1EDK02.QUALF 的所有记录?

代码是

SELECT 
t.c.query('E1EDK01/BELNR').value('.','char(15)') as INV_NO,
 t.c.query('E1EDKA1/PARVW').value('.','char(10)') as CUST_NO,
 t.c.query('E1EDKA1/NAME1').value('.','char(50)') as CUST_NAME,
 t.c.query('E1EDK02/QUALF').value('.','char(50)') as QUALF
FROM @XML.nodes('//*:ZINVOIC2/*:IDOC') t(c);

我该如何解决这个问题。我有多个这样的属性,不想为每个创建不同的查询,然后返回结果。

 <ZINVOIC2>
  <IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1">
      <TABNAM>EDI_DC40</TABNAM>
      <MANDT>100</MANDT>
      <DOCNUM>0000022222017973</DOCNUM>
       </EDI_DC40>
    <!--header general data information-->
    <E1EDK01 SEGMENT="1">
      <CURCY>GBP</CURCY>
      <HWAER>GBP</HWAER>
      <BELNR>9650019904</BELNR>
      <FKTYP>L</FKTYP>
      <Z1EDK01 SEGMENT="1">
        <TAXID>37-1652702</TAXID>
      </Z1EDK01>
      <Z1INCO SEGMENT="1">
        <INCO1>EXW</INCO1>
        <INCO1_TXT>Ex Works</INCO1_TXT>
      </Z1INCO>
      <ZINVREF SEGMENT="1">
        <ZNETDT>20220125</ZNETDT>
        <ZDSDT1>20220125</ZDSDT1>
        <DISCOUNTDUE>12427.39</DISCOUNTDUE>
        <SFAKN>N</SFAKN>
        <KALSM>YIS001</KALSM>
        <ZCONTACT_NUM>01542 832327</ZCONTACT_NUM>
        <FKART>YRIN</FKART>
        <KNUMV>0008498319</KNUMV>
        <VBTYP>M</VBTYP>
        <BEZEI>Ex Works</BEZEI>
        <KSCHL>ZMP6</KSCHL>
      </ZINVREF>
    </E1EDK01>
    <E1EDKA1 SEGMENT="1">
      <PARVW>RS</PARVW>
      <LIFNR>1111164896</LIFNR>
      <NAME1>XYZ Company</NAME1>
      <NAME2>XYZ Company Limited</NAME2>
      <STRAS>Sugarland str</STRAS>
      <ORT01>LONDON</ORT01>
      <PSTLZ>EC1A 4HD</PSTLZ>
      <LAND1>GB</LAND1>
      <SPRAS>E</SPRAS>
      <BNAME>PRODERP</BNAME>
      <PAORG>MK40</PAORG>
    </E1EDKA1>
    <E1EDKA1 SEGMENT="1">
      <PARVW>AG</PARVW>
      <PARTN>1111164896</PARTN>
      <NAME1>OILS LTD</NAME1>
      <STRAS>MARINE PLACE</STRAS>
      <ORT01>BUCKIE</ORT01>
      <PSTLZ>AB56 1UT</PSTLZ>
      <LAND1>GB</LAND1>
      <TELF1>01542 832327</TELF1>
      <TELFX>01542 833319</TELFX>
      <SPRAS>E</SPRAS>
      <REGIO>MR</REGIO>
      <SPRAS_ISO>EN</SPRAS_ISO>
    </E1EDKA1>
    <E1EDKA1 SEGMENT="1">
      <PARVW>RE</PARVW>
      <PARTN>1111164896</PARTN>
      <NAME1>OILS LTD</NAME1>
      <STRAS>MARINE PLACE</STRAS>
      <ORT01>BUCKIE</ORT01>
      <PSTLZ>AB56 1UT</PSTLZ>
      <LAND1>GB</LAND1>
      <TELF1>01542 832327</TELF1>
      <TELFX>01542 833319</TELFX>
      <SPRAS>E</SPRAS>
      <REGIO>MR</REGIO>
      <SPRAS_ISO>EN</SPRAS_ISO>
    </E1EDKA1>
    <E1EDKA1 SEGMENT="1">
      <PARVW>RG</PARVW>
      <PARTN>1111164896</PARTN>
      <NAME1>OILS LTD</NAME1>
      <STRAS>MARINE PLACE</STRAS>
      <ORT01>BUCKIE</ORT01>
      <PSTLZ>AB56 1UT</PSTLZ>
      <LAND1>GB</LAND1>
      <TELF1>01542 832327</TELF1>
      <TELFX>01542 833319</TELFX>
      <SPRAS>E</SPRAS>
      <REGIO>MR</REGIO>
      <SPRAS_ISO>EN</SPRAS_ISO>
    </E1EDKA1>
    <E1EDKA1 SEGMENT="1">
      <PARVW>BK</PARVW>
      <LIFNR>1040</LIFNR>
      <NAME1>XYZ Mktg Br</NAME1>
      <NAME2>ABC Ltd</NAME2>
      <STRAS>Sugarstreet</STRAS>
      <ORT01>LONDON</ORT01>
      <PSTLZ>EC1A 4HD</PSTLZ>
      <LAND1>GB</LAND1>
    </E1EDKA1>
    <!--header reference data-->
    <E1EDK02 SEGMENT="1">
      <QUALF>009</QUALF>
      <BELNR>9659999904</BELNR>
      <DATUM>20220101</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>002</QUALF>
      <BELNR>0201555555</BELNR>
      <DATUM>20220120</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>012</QUALF>
      <BELNR>0082222514</BELNR>
      <DATUM>20210423</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>017</QUALF>
      <BELNR>9650019904</BELNR>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>087</QUALF>
      <BELNR>9650019904</BELNR>
    </E1EDK02>`enter code here`
    <!--date segment-->
    <E1EDK03 SEGMENT="1">
      <IDDAT>026</IDDAT>
      <DATUM>20220120</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>001</IDDAT>
      <DATUM>20210423</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>012</IDDAT>
      <DATUM>20220120</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>011</IDDAT>
      <DATUM>20220120</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>024</IDDAT>
      <DATUM>20220101</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>028</IDDAT>
      <DATUM>20220115</DATUM>
    </E1EDK03>
    <E1EDK03 SEGMENT="1">
      <IDDAT>048</IDDAT>
      <DATUM>20220101</DATUM>
    </E1EDK03>
    <!--taxes-->
    <E1EDK04 SEGMENT="1">
      <MWSKZ>G1</MWSKZ>
      <MSATZ>20.000</MSATZ>
      <MWSBT>1394.86</MWSBT>
    </E1EDK04>
  </IDOC>
</ZINVOIC2> 

E1EDK02/QUALF 值决定了 E1EDK02 内容的性质,您可以像这样将它们交叉应用于 IDOC 元素(中间文档)...

declare @xml xml =
N'<INVOIC02 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="INVOIC02.xsd">
  <IDOC BEGIN="1">
    <EDI_DC40 SEGMENT="1" />
    <E1EDK02 SEGMENT="1">
      <QUALF>009</QUALF>
      <BELNR>239238232</BELNR>
      <DATUM>20190111</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>001</QUALF>
      <BELNR>592382323</BELNR>
      <DATUM>20190104</DATUM>
    </E1EDK02>
    <E1EDK02 SEGMENT="1">
      <QUALF>002</QUALF>
      <BELNR>292847342</BELNR>
      <DATUM>20190104</DATUM>
    </E1EDK02>
  </IDOC>
</INVOIC02>';

select
  InvoiceNumber.value('(QUALF/text())[1]', 'varchar(3)') as Invoice_QUALF,
  InvoiceNumber.value('(BELNR/text())[1]', 'varchar(35)') as Invoice_BELNR,
  InvoiceNumber.value('(DATUM/text())[1]', 'date') as Invoice_DATUM,
  InvoiceNumber.value('(UZEIT/text())[1]', 'time') as Invoice_UZEIT,

  CustomerPurchaseOrderNumber.value('(QUALF/text())[1]', 'varchar(3)') as PurchaseOrder_QUALF,
  CustomerPurchaseOrderNumber.value('(BELNR/text())[1]', 'varchar(35)') as PurchaseOrder_BELNR,
  CustomerPurchaseOrderNumber.value('(DATUM/text())[1]', 'date') as PurchaseOrder_DATUM,
  CustomerPurchaseOrderNumber.value('(UZEIT/text())[1]', 'time') as PurchaseOrder_UZEIT,

  SupplierOrderNumber.value('(QUALF/text())[1]', 'varchar(3)') as SupplierOrder_QUALF,
  SupplierOrderNumber.value('(BELNR/text())[1]', 'varchar(35)') as SupplierOrder_BELNR,
  SupplierOrderNumber.value('(DATUM/text())[1]', 'date') as SupplierOrder_DATUM,
  SupplierOrderNumber.value('(UZEIT/text())[1]', 'time') as SupplierOrder_UZEIT

from @xml.nodes('/INVOIC02/IDOC') as IDOC(IntermediateDocument)
cross apply IntermediateDocument.nodes('E1EDK02[QUALF/text()="009"]') E1EDK02_009(InvoiceNumber)
cross apply IntermediateDocument.nodes('E1EDK02[QUALF/text()="001"]') E1EDK02_001(CustomerPurchaseOrderNumber)
cross apply IntermediateDocument.nodes('E1EDK02[QUALF/text()="002"]') E1EDK02_002(SupplierOrderNumber);
Invoice_QUALF Invoice_BELNR Invoice_DATUM Invoice_UZEIT PurchaseOrder_QUALF PurchaseOrder_BELNR PurchaseOrder_DATUM PurchaseOrder_UZEIT SupplierOrder_QUALF SupplierOrder_BELNR SupplierOrder_DATUM SupplierOrder_UZEIT
009 239238232 2019-01-11 null 001 592382323 2019-01-04 null 002 292847342 2019-01-04 null

编辑:在问题中提供了示例 ZINVOIC2 数据后...

以下查询将生成您要求的结果集,但根据您的目标,该结果集可能不会完全有用,因为它将 iDoc 合作伙伴资料数据与 iDoc 参考数据相乘:

select 
  GeneralData.value('(BELNR/text())[1]', 'char(15)') as INV_NO,
  PartnerProfile.value('(PARVW/text())[1]', 'char(10)') as CUST_NO,
  PartnerProfile.value('(NAME1/text())[1]', 'char(50)') as CUST_NAME,
  ReferenceData.value('(QUALF/text())[1]', 'char(50)') as QUALF
from @XML.nodes('/ZINVOIC2/IDOC') IDOC(IntermediateDocument)
cross apply IntermediateDocument.nodes('E1EDK01') E1EDK01(GeneralData)
cross apply IntermediateDocument.nodes('E1EDKA1') E1EDKA1(PartnerProfile)
cross apply IntermediateDocument.nodes('E1EDK02') E1EDK02(ReferenceData)
order by row_number() over (order by ReferenceData, PartnerProfile);
INV_NO CUST_NO CUST_NAME QUALF
9650019904 RS XYZ Company 009
9650019904 AG OILS LTD 009
9650019904 RE OILS LTD 009
9650019904 RG OILS LTD 009
9650019904 BK XYZ Mktg Br 009
9650019904 RS XYZ Company 002
9650019904 AG OILS LTD 002
9650019904 RE OILS LTD 002
9650019904 RG OILS LTD 002
9650019904 BK XYZ Mktg Br 002
9650019904 RS XYZ Company 012
9650019904 AG OILS LTD 012
9650019904 RE OILS LTD 012
9650019904 RG OILS LTD 012
9650019904 BK XYZ Mktg Br 012
9650019904 RS XYZ Company 017
9650019904 AG OILS LTD 017
9650019904 RE OILS LTD 017
9650019904 RG OILS LTD 017
9650019904 BK XYZ Mktg Br 017
9650019904 RS XYZ Company 087
9650019904 AG OILS LTD 087
9650019904 RE OILS LTD 087
9650019904 RG OILS LTD 087
9650019904 BK XYZ Mktg Br 087