SQL XML 每行多个元素

SQL XML Multiple Elements Per Row

我的设置如下:

TableA - ID, PolicyReference, PolicyNumber

TableB - ID, Drivers, DOB, Sex

一条记录被插入到表 A 中,该记录具有唯一 ID、策略参考和该策略的策略编号。

然后每个 'Policy' 可以在该策略上有多个 driver,在 TableB 中 ID 是唯一的并且是 TableA 和 TableB 之间的 JOIN,现在我已经写了我的 SELECT XML 直到此时查询都很好,因为当我不包括 TableB 时,它 return 每条记录 1 行,但是当我包括 TableB 时,如果有超过 1 driver 这个搞砸了。

下面是示例 XML 我目前 return 第 1 行:

<PCNewBusiness>
<PolicyNumber>999999999</PolicyNumber>
<StartDate>2016-10-17T00:00:002017-10-17T00:00:00</StartDate>
<Premium>
  <NetAmount>100.00</NetAmount>
  <IPT>10.00</IPT>
</Premium>
<Fee>
  <NetAmount>50.00</NetAmount>
  <IPT>0</IPT>
</Fee>
<Policyholder>
  <PolicyholderType>
    <PrivateIndividual>
      <Name>
        <Title>Mr</Title>
        <FirstNames>Bob</FirstNames>
        <LastName>Test</LastName>
      </Name>
      <DateOfBirth>1985-12-03T00:00:00</DateOfBirth>
      <MaritalStatus>Single</MaritalStatus>
      <Sex>Male</Sex>
    </PrivateIndividual>
  </PolicyholderType>
  <Contact>Mr Bob Test</Contact>
  <Address>
    <Address1>This</Address1>
    <Address2>Test</Address2>
    <Address3>Address</Address3>
    <Address4>Is Fake</Address4>
    <Postcode>BB2 1AB</Postcode>
  </Address>
  <Phone>07777777777</Phone>
  <Email>mytestaccount@gmail.com</Email>
</Policyholder>
<Cover>
  <CoverType>Comprehensive</CoverType>
  <PolicyExcess>600</PolicyExcess>
  <NoClaimsBonusYears>9</NoClaimsBonusYears>
  <NCBOtherVehicle>0</NCBOtherVehicle>
  <Use>Class1</Use>
</Cover>

现在,当我加入 TableB 时,它 return 上面的信息是两次,我知道这是因为 ID 上的联接识别出 TableB 中有 2 行 returned 因为有2 drivers.

这将是我加入 TableB 时的预期输出。

<Cover>
    <CoverType>Comprehensive</CoverType>
    <PolicyExcess>600</PolicyExcess>
    <NoClaimsBonusYears>9</NoClaimsBonusYears>
    <NCBOtherVehicle>0</NCBOtherVehicle>
    <Use>Class1</Use>
</Cover>
<Drivers>
    <Driver>
        <RelationshipToPolicyholder>Policyholder</RelationshipToPolicyholder>
        <Name>
            <Title>Mr</Title>
            <FirstNames>Bob</FirstNames>
            <LastName>Test</LastName>
        </Name>
        <DateOfBirth>1972-07-14</DateOfBirth>
        <LicenceType>FullUK</LicenceType>
        <PeriodLicenceHeld>MoreThanFiveYears</PeriodLicenceHeld>
        <HomeAddress>
            <Address1>Another Test</Address1>
            <Address2>Address</Address2>
            <Address3>Thats Fake</Address3>
            <Postcode>AA1 1ZZ</Postcode>
        </HomeAddress>
        <PeriodResident>MoreThanFiveYears</PeriodResident>
        <VehicleUseFrequency>Daily</VehicleUseFrequency>
        <HasUseOfOtherVehicle>false</HasUseOfOtherVehicle>
        <MainOccupation>Software Engineer</MainOccupation>
        <HasCriminalConvictions>1</HasCriminalConvictions>
    </Driver>
    <Driver>
        <RelationshipToPolicyholder>Spouse</RelationshipToPolicyholder>
        <Name>
            <Title>Mrs</Title>
            <FirstNames>Jill</FirstNames>
            <LastName>Test</LastName>
        </Name>
        <DateOfBirth>1972-07-14</DateOfBirth>
        <LicenceType>FullUK</LicenceType>
        <PeriodLicenceHeld>MoreThanFiveYears</PeriodLicenceHeld>
        <HomeAddress>
            <Address1>Another</Address1>
            <Address2>Test</Address2>
            <Address3>Address</Address3>
            <Postcode>BB1 1BZ</Postcode>
        </HomeAddress>
        <PeriodResident>MoreThanFiveYears</PeriodResident>
        <VehicleUseFrequency>Daily</VehicleUseFrequency>
        <HasUseOfOtherVehicle>false</HasUseOfOtherVehicle>
        <MainOccupation>Housewife</MainOccupation>
        <HasCriminalConvictions>1</HasCriminalConvictions>
    </Driver>
</Drivers>

所以基本上我想要 return 1 行数据,但是当我加入 TableB 时,我需要使用 TableB 中 2 行的数据来填充 'Drivers' 元素之间的所有内容。

需要更多信息请开火。

更新

我现在 SELECT 按要求查询。

SELECT  ROW_NUMBER() OVER ( ORDER BY ( SELECT   NULL
                                 ) ) AS "PolicyRecordNumber",
    sub.Polno AS "PCNewBusiness/PolicyNumber",
    sub.[Inception Date] AS "PCNewBusiness/StartDate",
    sub.[Renewal Date] AS "PCNewBusiness/StartDate",
    sub.PremXIPT AS "PCNewBusiness/Premium/NetAmount",
    sub.PremIPT AS "PCNewBusiness/Premium/IPT",
    sub.FeeXIPT AS "PCNewBusiness/Fee/NetAmount",
    sub.FeeIPT AS "PCNewBusiness/Fee/IPT",
    ph.Title AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/Name/Title",
    ph.Firstname AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/Name/FirstNames",
    ph.Surname AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/Name/LastName",
    ph.DateOfBirth AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/DateOfBirth",
    ph.MaritalStatus AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/MaritalStatus",
    ph.Sex AS "PCNewBusiness/Policyholder/PolicyholderType/PrivateIndividual/Sex" ,
    ph.Contact AS "PCNewBusiness/Policyholder/Contact",
    ph.Addr1 AS "PCNewBusiness/Policyholder/Address/Address1",
    ph.Addr2 AS "PCNewBusiness/Policyholder/Address/Address2",
    ph.Addr3 AS "PCNewBusiness/Policyholder/Address/Address3",
    ph.Addr4 AS "PCNewBusiness/Policyholder/Address/Address4",
    ph.Pcode AS "PCNewBusiness/Policyholder/Address/Postcode",
    ISNULL(ph.Tel,ph.Tel2) AS "PCNewBusiness/Policyholder/Phone",
    ph.Email AS "PCNewBusiness/Policyholder/Email",
    cov.Cover AS "PCNewBusiness/Cover/CoverType",
    cov.Excess AS "PCNewBusiness/Cover/PolicyExcess",
    cov.NCBYears AS "PCNewBusiness/Cover/NoClaimsBonusYears",
    cov.NCBOtherVeh AS "PCNewBusiness/Cover/NCBOtherVehicle",
    cov.ClassOfUse AS "PCNewBusiness/Cover/Use",
    --dri.RelationshipToPH AS "PCNewBusiness/Drivers/Driver/RelationshipToPolicyHolder",
    --dri.Drivertitle AS "PCNewBusiness/Drivers/Driver/Title" ,
    --dri.FirstName AS "PCNewBusiness/Drivers/Driver/FirstNames" ,
    --dri.Surname AS "PCNewBusiness/Drivers/Driver/LastName"
    veh.Make AS "PCNewBusiness/Vehicles/Vehicle/Make",
    veh.Model AS "PCNewBusiness/Vehicles/Vehicle/Model",
    veh.Reg AS "PCNewBusiness/Vehicles/Vehicle/RegistrationNumber",
    veh.Body AS "PCNewBusiness/Vehicles/Vehicle/BodyType",
    veh.Parking AS "PCNewBusiness/Vehicles/Vehicle/LocationWhenNotInUse",
    '' AS "PCNewBusiness/Vehicles/Vehicle/AnnualMileage",
    veh.YearMade AS "PCNewBusiness/Vehicles/Vehicle/YearOfManufacture",
    veh.Engine_size AS "PCNewBusiness/Vehicles/Vehicle/EngineSizeCc",
    veh.Purchasedate AS "PCNewBusiness/Vehicles/Vehicle/PurchaseDate",
    veh.Value AS "PCNewBusiness/Vehicles/Vehicle/PurchasePrice",
    veh.Value1 AS "PCNewBusiness/Vehicles/Vehicle/EstimatedValue",
    veh.Seats AS "PCNewBusiness/Vehicles/Vehicle/NumberOfSeats",
    veh.RightHandDrive AS "PCNewBusiness/Vehicles/Vehicle/RightHandDrive",
    veh.Fuel AS "PCNewBusiness/Vehicles/Vehicle/FuelType"
FROM    dbo.Submissions sub
    LEFT OUTER JOIN dbo.PolicyHolder ph ON ph.ID = sub.ID
    LEFT OUTER JOIN dbo.Cover cov ON cov.ID = sub.ID
    --LEFT OUTER JOIN dbo.Drivers dri ON dri.ID = sub.ID
    LEFT OUTER JOIN dbo.Vehicle veh ON veh.ID = sub.ID
    --LEFT OUTER JOIN dbo.Convictions con ON con.ID = sub.ID
    --LEFT OUTER JOIN dbo.Claims cla ON cla.ID = sub.ID
    --LEFT OUTER JOIN dbo.Medical med ON med.ID = sub.ID
WHERE sub.[Transaction] = 'New Business' AND sub.[Ledger Date] >= dbo.Today()-7
FOR     XML PATH('Policy')

更新 2

好的,我已经为我的 'Drivers' Select 输入了 sub-query,如下所示:

   cov.Cover AS "PCNewBusiness/Cover/CoverType" ,
    cov.Excess AS "PCNewBusiness/Cover/PolicyExcess" ,
    cov.NCBYears AS "PCNewBusiness/Cover/NoClaimsBonusYears" ,
    cov.NCBOtherVeh AS "PCNewBusiness/Cover/NCBOtherVehicle" ,
    cov.ClassOfUse AS "PCNewBusiness/Cover/Use" ,
    ( SELECT    dri1.ID ,
                RelationshipToPH ,
                dri1.FirstName ,
                dri1.Surname
      FROM      dbo.Drivers dri1
                INNER JOIN dbo.Submissions sub1 ON sub1.ID = dri1.ID
    FOR
      XML PATH('Driver') ,
          TYPE
    ) AS "PCNewBusiness/Drivers" 

这个 return 驱动程序在我需要它们的地方但是,子查询正在通过 'Drivers' table 中的每一行而不是每个 table 的相关行=61=] 用于该唯一 ID。

见下文:

    <Cover>
  <CoverType>Comprehensive</CoverType>
  <PolicyExcess>600</PolicyExcess>
  <NoClaimsBonusYears>4</NoClaimsBonusYears>
  <NCBOtherVehicle>0</NCBOtherVehicle>
  <Use>Class1</Use>
</Cover>
<Drivers>
  <Driver>
    <ID>1</ID>
    <RelationshipToPH>Policyholder</RelationshipToPH>
    <FirstName>John</FirstName>
    <Surname>Doe</Surname>
  </Driver>
  <Driver>
    <ID>2</ID>
    <RelationshipToPH>Commonlaw Spouse</RelationshipToPH>
    <FirstName>Bob</FirstName>
    <Surname>Test</Surname>
  </Driver>
  <Driver>
    <ID>2</ID>
    <RelationshipToPH>Policyholder</RelationshipToPH>
    <FirstName>Jill</FirstName>
    <Surname>Test</Surname>
  </Driver>
  <Driver>
    <ID>3</ID>
    <RelationshipToPH>Policyholder</RelationshipToPH>
    <FirstName>Jane</FirstName>
    <Surname>Gowe</Surname>
  </Driver>
  <Driver>
    <ID>4</ID>
    <RelationshipToPH>Policyholder</RelationshipToPH>
    <FirstName>Dave</FirstName>
    <Surname>Grace</Surname>
  </Driver>

我的第一行应该只有 return 例如 ID 为“2”的 2 个驱动程序。

你自己的更新 2 正是我想建议你的东西...

现在我觉得剩下的很简单了:

将您的子select的JOIN更改为简单的WHERE:

(SELECT    dri1.ID ,
            RelationshipToPH ,
            dri1.FirstName ,
            dri1.Surname
  FROM      dbo.Drivers dri
  WHERE dri.ID=sub.ID
FOR
  XML PATH('Driver') ,
      TYPE
) AS "PCNewBusiness/Drivers",