如何查询父级重复节点内的重复XML子节点?

时间:2019-01-16 21:46:13

标签: sql-server

我将以下XML存储在nText列中(不是我的设计,较旧的数据库)。我需要提取PolicyNumber和CvgCode,它是Coverage子节点的属性。

<efs:Request 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:efs="http://www.slsot.org/efs" 
xsi:schemaLocation="http://www.slsot.org/efs 
http://efs.slsot.org/efs/xsd/SlsotEfsSchema2.xsd">
  <EfsVersion>2.0</EfsVersion>
  <Batch BatchType="N" AgLicNo="12345" ItemCnt="69">
    <EFSPolicy>
      <PolicyNumber>POL12345</PolicyNumber>
      <Binder>0086592YZ</Binder>
      <TransType>N</TransType>
      <Insured>Dummy Co LLC</Insured>
      <ZipCode>75225</ZipCode>
      <ClassCd>99930</ClassCd>
      <PolicyFee>35.00</PolicyFee>
      <TotalTax>36.62</TotalTax>
      <TotalStampFee>1.13</TotalStampFee>
      <TotalGross>792.75</TotalGross>
      <EffectiveDate>09/17/2018</EffectiveDate>
      <ExpirationDate>09/17/2019</ExpirationDate>
      <IssueDate>09/20/2018</IssueDate>
      <ContUntilCancl>N</ContUntilCancl>
      <FedCrUnion>N</FedCrUnion>
      <AORFlag>N</AORFlag>
      <CustomID>043684</CustomID>
      <WindStormExclusion>N</WindStormExclusion>
      <CorrectionReEntry>N</CorrectionReEntry>
      <Coverages>
        <Coverage CvgCode="9325">720.00</Coverage>
      </Coverages>
      <Securities>
        <Company CoNumber="80101168">100.00</Company>
      </Securities>
    </EFSPolicy>
    <EFSPolicy>
    ...
    </EFSPolicy>
  </Batch>
</efs:Request>

这是我用来提取PolicyNumber的SQL代码(到目前为止)。

with cte_table(BatchID, xmlData)
AS
(SELECT BatchID, CAST(CAST(xmlData AS VARCHAR(MAX)) AS XML) from 
Batches)
select
    s.BatchID
    ,t.c.value('PolicyNumber[1]', 'varchar(max)') as PolicyNumber
from cte_table as s
    cross apply s.xmlData.nodes('/*:Request/Batch/EFSPolicy') as t(c)
where BatchID in (select batchID from Batches where CreateDate between '1/1/19' and getdate())

我已经在Coverage节点上尝试了第二个CROSS APPLY,但这为每个批次提供了所有Coverage值(不是CvgCode属性),所以我的结果集是行数的100倍以上。我认为这是由于第二次CROSS APPLY引起的,是否存在INNER JOIN类型的CROSS APPLY?

1 个答案:

答案 0 :(得分:1)

您需要声明名称空间以检索数据:

DECLARE @XML xml = '<efs:Request 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:efs="http://www.slsot.org/efs" 
xsi:schemaLocation="http://www.slsot.org/efs 
http://efs.slsot.org/efs/xsd/SlsotEfsSchema2.xsd">
  <EfsVersion>2.0</EfsVersion>
  <Batch BatchType="N" AgLicNo="12345" ItemCnt="69">
    <EFSPolicy>
      <PolicyNumber>POL12345</PolicyNumber>
      <Binder>0086592YZ</Binder>
      <TransType>N</TransType>
      <Insured>Dummy Co LLC</Insured>
      <ZipCode>75225</ZipCode>
      <ClassCd>99930</ClassCd>
      <PolicyFee>35.00</PolicyFee>
      <TotalTax>36.62</TotalTax>
      <TotalStampFee>1.13</TotalStampFee>
      <TotalGross>792.75</TotalGross>
      <EffectiveDate>09/17/2018</EffectiveDate>
      <ExpirationDate>09/17/2019</ExpirationDate>
      <IssueDate>09/20/2018</IssueDate>
      <ContUntilCancl>N</ContUntilCancl>
      <FedCrUnion>N</FedCrUnion>
      <AORFlag>N</AORFlag>
      <CustomID>043684</CustomID>
      <WindStormExclusion>N</WindStormExclusion>
      <CorrectionReEntry>N</CorrectionReEntry>
      <Coverages>
        <Coverage CvgCode="9325">720.00</Coverage>
      </Coverages>
      <Securities>
        <Company CoNumber="80101168">100.00</Company>
      </Securities>
    </EFSPolicy>
    <EFSPolicy>
    </EFSPolicy>
  </Batch>
</efs:Request>';

WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as xsi,
                   'http://www.slsot.org/efs' AS efs)
SELECT EFS.[Policy].value('(./PolicyNumber/text())[1]','varchar(25)') AS PolicyNumber,
       EFS.[Policy].value('(./Coverages/Coverage/@CvgCode)[1]','int') AS CvgCode --Assumes only 1 CvgCode per policy
FROM (VALUES(@XML)) V(X)
     CROSS APPLY V.X.nodes('efs:Request/Batch/EFSPolicy') EFS([Policy]);