Sql 使用xml.nodes解析xml文件时,数据库中存在重复行

Sql 使用xml.nodes解析xml文件时,数据库中存在重复行,sql,xml,duplicates,Sql,Xml,Duplicates,我已成功地将大部分XML文件解析到数据库中,但我对以下节点/数据有问题 XML数据示例: 我为每种不同的旅行类型设置了一个case when,但是它为每种case when复制了数据库中的行。有没有办法避免这种情况 SELECT XC.value('../../@TransactionType', 'varchar(50)') TransactionType, XC.value('../../@OrderItemRef', 'bigint')OrderRef, XC.value('..

我已成功地将大部分XML文件解析到数据库中,但我对以下节点/数据有问题

XML数据示例:

我为每种不同的旅行类型设置了一个case when,但是它为每种case when复制了数据库中的行。有没有办法避免这种情况

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' 
输出如下所示:


您没有显示足够的查询,但我的魔镜灯泡告诉我,您正在使用
将xml.nodes(…)作为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 
其思想是:进行深入搜索(因此在
碳排放
之前进行
/
)并找到第一个元素,其中
传输类型
等于给定的字符串

一般来说,最好指定完整(或相对)的
XPath
而不是执行深度搜索,因此最好使用较长的路径,而不是
///CarbonEmissions
,但我不知道您的XML

更新 我的魔幻玻璃灯泡像这样低语:

  • 刚刚从最后一个
    apply.nodes()
  • 直接调用元素,无需使用
    大小写
祝你好运

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'

很抱歉,我知道其余的SQL作品,所以我并没有真正考虑把它全部发布——我会在几分钟内把整个事情发布出来。Cheers@DaveEdmonds这将有助于提供一个可复制粘贴(简化)的XML样本。嗨,恐怕不行。数据安全性很高。我很感激它限制了你能提供多少帮助。我会看看你上面的建议,看看是否能奏效。谢谢Dave@DaveEdmonds如果我看到这个XML,我很确定这可以做得更好/更直接。。。也许-如果性能很重要-你想准备一个测试样本。。。不管怎样,我只是在问了我的魔镜灯泡后更新了一下。。。