使用xml.nodes解析xml文件时数据库中的行重复

时间:2017-01-17 15:49:09

标签: sql xml duplicates

我已成功将大部分XML文件解析到我的数据库中,但是我遇到以下节点/数据的问题。

XML数据示例:

enter image description here

我为每个不同的旅行类型设置了一个案例,但是它为每个案例时刻重复了数据库中的行。关于如何避免这种想法的任何想法?

SELECT

 XC.value('../../@TransactionType', 'varchar(50)') TransactionType,
 XC.value('../../@OrderItemRef', 'bigint')OrderRef,
 XC.value('../../@TransactionDate', 'datetime')TransDate,
 XC.value('../@JourneyTime', 'int')JourneyTime,
 XC.value('../@Distance', 'nvarchar(10)' )Distance,
 XC.value('@Ref', 'varchar(50)' )TicketRef,
 ADC.value('@Organisation', 'varchar(50)' )Client,
 ACC.value('@ExternalRef', 'varchar(50)' )Account,
 DCC.value('@Address[1]', 'varchar(50)' )contactEmail,
 BAC.value('@FirstName','varchar(50)' ) + ' ' + BAC.value         ('@LastName','varchar(50)' ) Booker,
 PC.value('@FirstName','varchar(50)' )travellerforename,
 PC.value('@LastName','varchar(50)' )travellersurname,
 ORC.value('@Name','Varchar(50)' )Origin,
 DESTC.value('@Name','Varchar(50)' )Destination,
 XC.value('@Route', 'varchar(50)' )Route,
 XC.value('@Class' , 'varchar(50)' )Class,
 XC.value('@Code' , 'varchar(50)' )TicketCode,
 XC.value('@Name' , 'varchar(50)' )TicketType,
 TOPC.value('@Name' , 'varchar(50)' )TrainOperator,
 LEGC.value('@Departure' , 'Datetime' )TravelDate,
 FAREC.value('@TotalAmount' , 'nvarchar(10)' )Fare,
 FAREXC.value('@OfferedFare' , 'nvarchar(10)' )LowFare,
 FAREXC.value('@NormalFare' , 'nvarchar(10)' )HighFare,
 IDC.value('../@DeliveryMethod' , 'nvarchar(10)' )fulfilmentType,
 FAREXC.value('@Reason' , 'varchar(50)' ) travelreason,

 case when(CEC.value('@TransportType' , 'varchar(50)') = 'Rail') then
 CEC.value('@Emissions', 'decimal(4,2)')
 END AS [railCo2],
   case when(CEC.value('@TransportType' , 'varchar(50)') = 'Aeroplane') then
CEC.value('@Emissions', 'decimal(4,2)')
END AS [airCo2],
  case when(CEC.value('@TransportType' , 'varchar(50)') = 'Car - Diesel') then
CEC.value('@Emissions', 'decimal(4,2)')
END AS [CarDieselCo2],
case when(CEC.value('@TransportType' , 'varchar(50)') = 'Car - Petrol') then
CEC.value('@Emissions', 'decimal(4,2)')
END AS [CarDieselCo2],
case when(CEC.value('@TransportType' , 'varchar(50)') = 'Motorcycle') then
CEC.value('@Emissions', 'decimal(4,2)')
END AS [MotorcycleCo2]

FROM TempXML

cross apply
XMLData.nodes('my:Handoff/ImmediateDetail') AS IDT(IDC)
Cross Apply
IDC.nodes('Segment[1]/Ticket') AS XT(XC)
Cross apply 
IDC.nodes('AccountContact/Address') AS ADT(ADC)
Cross apply 
IDC.nodes('Account') AS ACT(ACC)
Cross apply 
IDC.nodes('DeliveryContact/Email') AS DCT(DCC)
cross apply 
IDC.nodes('BookingAgent/Person') AS BAT(BAC)
cross apply 
IDC.nodes('PassengerGroup/Passenger/Person') AS PT(PC)
cross apply
IDC.nodes('Segment[1]/Origin') AS ORT(ORC)
cross apply
IDC.nodes('Segment[1]/Destination') AS DESTT(DESTC)
cross apply
IDC.nodes('Segment[1]/Leg[1]') AS LEGT(LEGC)
cross apply
IDC.nodes('Segment[1]/Leg[1]/TOC') AS TOPT(TOPC)
cross apply
IDC.nodes('Segment[1]/Ticket/Sale/Fare') AS FARET(FAREC)
cross apply
IDC.nodes('Segment[1]/Ticket/FareException') AS FAREXT(FAREXC)
cross apply
IDC.nodes('Segment[1]/CarbonEmissionDetails/CarbonEmissions') AS CET(CEC)


WHERE 

LEGC.value('@Direction'  , 'varchar(50)' ) = 'Outbound' 

输出如下:

enter image description here

1 个答案:

答案 0 :(得分:1)

您没有显示足够多的查询,但我的神奇玻璃灯泡告诉我,您正在使用APPLY YourXML.nodes(...) AS x(CEC)来逐行检索。每行都带有一个值,因此您的结果集每行将有一个值。

取消此.nodes() - 致电并尝试使用以下内容:

SELECT SomeColumns
      ,YourXml.value(N'(//CarbonEmissions[@TransportType="Rail"]/@Emission)[1]',N'decimal(10,4)') AS railCo2 
      ,YourXml.value(N'(//CarbonEmissions[@TransportType="Aeroplane"]/@Emission)[1]',N'decimal(10,4)') AS airCo2

      ,more columns like this 

这个想法是:执行深度搜索(因此//之前的CarbonEmissions)并找到第一个元素,其中TransportType等于字符串。

一般情况下,最好指定完整(或相对)XPath而不是执行深度搜索,因此最好使用较长的路径而不是//CarbonEmissions,但我不喜欢&# 39;不知道你的XML ......

更新

我的神奇玻璃灯泡低声说出这样的话:

  • 刚删除了上一个apply .nodes()
  • 中的一个节点
  • 直接调用元素而不使用case
祝你好运!

SELECT

 XC.value('../../@TransactionType', 'varchar(50)') TransactionType,
 XC.value('../../@OrderItemRef', 'bigint')OrderRef,
 XC.value('../../@TransactionDate', 'datetime')TransDate,
 XC.value('../@JourneyTime', 'int')JourneyTime,
 XC.value('../@Distance', 'nvarchar(10)' )Distance,
 XC.value('@Ref', 'varchar(50)' )TicketRef,
 ADC.value('@Organisation', 'varchar(50)' )Client,
 ACC.value('@ExternalRef', 'varchar(50)' )Account,
 DCC.value('@Address[1]', 'varchar(50)' )contactEmail,
 BAC.value('@FirstName','varchar(50)' ) + ' ' + BAC.value         ('@LastName','varchar(50)' ) Booker,
 PC.value('@FirstName','varchar(50)' )travellerforename,
 PC.value('@LastName','varchar(50)' )travellersurname,
 ORC.value('@Name','Varchar(50)' )Origin,
 DESTC.value('@Name','Varchar(50)' )Destination,
 XC.value('@Route', 'varchar(50)' )Route,
 XC.value('@Class' , 'varchar(50)' )Class,
 XC.value('@Code' , 'varchar(50)' )TicketCode,
 XC.value('@Name' , 'varchar(50)' )TicketType,
 TOPC.value('@Name' , 'varchar(50)' )TrainOperator,
 LEGC.value('@Departure' , 'Datetime' )TravelDate,
 FAREC.value('@TotalAmount' , 'nvarchar(10)' )Fare,
 FAREXC.value('@OfferedFare' , 'nvarchar(10)' )LowFare,
 FAREXC.value('@NormalFare' , 'nvarchar(10)' )HighFare,
 IDC.value('../@DeliveryMethod' , 'nvarchar(10)' )fulfilmentType,
 FAREXC.value('@Reason' , 'varchar(50)' ) travelreason,

 CEC.value(N'(CarbonEmissions[@TransportType="Rail"]/@Emission)[1]',N'decimal(10,4)') AS railCo2, 
 CEC.value(N'(CarbonEmissions[@TransportType="Aeroplane"]/@Emission)[1]',N'decimal(10,4)') AS airCo2

--more of the same

FROM TempXML

cross apply
XMLData.nodes('my:Handoff/ImmediateDetail') AS IDT(IDC)
Cross Apply
IDC.nodes('Segment[1]/Ticket') AS XT(XC)
Cross apply 
IDC.nodes('AccountContact/Address') AS ADT(ADC)
Cross apply 
IDC.nodes('Account') AS ACT(ACC)
Cross apply 
IDC.nodes('DeliveryContact/Email') AS DCT(DCC)
cross apply 
IDC.nodes('BookingAgent/Person') AS BAT(BAC)
cross apply 
IDC.nodes('PassengerGroup/Passenger/Person') AS PT(PC)
cross apply
IDC.nodes('Segment[1]/Origin') AS ORT(ORC)
cross apply
IDC.nodes('Segment[1]/Destination') AS DESTT(DESTC)
cross apply
IDC.nodes('Segment[1]/Leg[1]') AS LEGT(LEGC)
cross apply
IDC.nodes('Segment[1]/Leg[1]/TOC') AS TOPT(TOPC)
cross apply
IDC.nodes('Segment[1]/Ticket/Sale/Fare') AS FARET(FAREC)
cross apply
IDC.nodes('Segment[1]/Ticket/FareException') AS FAREXT(FAREXC)
cross apply
IDC.nodes('Segment[1]/CarbonEmissionDetails') AS CET(CEC)


WHERE 

LEGC.value('@Direction'  , 'varchar(50)' ) = 'Outbound'