棒球XML到SQL查询 - 优化

时间:2013-04-10 21:03:47

标签: sql-server xml

源数据看起来来自以下免费提供的描述大联盟棒球比赛的XML文件。

http://gd2.mlb.com/components/game/mlb/year_2013/month_04/day_09/gid_2013_04_09_atlmlb_miamlb_1/inning/

我创建了一个SQL Server表,其中包含每个GamePK /局的行,以及一个名为PBP的XML列。上面文件夹中的每个文件都成为此表中的一行。下面的查询是我尝试将XML解析为记录集。它工作但对于大量行来说非常慢,并且非常重复 - 似乎应该有一个更好的方法来做这个没有UNION子句。感谢任何有关改进/优化的帮助

select 
 i.GamePK
 ,inn.value('@num', 'int') as inning
 ,itop.value('1', 'int') as IsTop
 ,itop.value('@num', 'int') as abNum
 ,itop.value('@batter', 'int') as batter
--  clip

 ,itoppit.value('@des', 'varchar(32)') as pitdesc
 ,itoppit.value('@id', 'int') as seq
 ,itoppit.value('@type', 'varchar(8)') as pittype
-- clip 

 from tblInnings i
       cross apply PBP.nodes('/inning') as inn(inn)
       cross apply inn.nodes('top/atbat') as itop(itop)
       cross apply itop.nodes('pitch') as itoppit(itoppit)
union 
select 
 i.GamePK
 ,inn.value('@num', 'int') as inning
 ,ibot.value('0', 'int') as IsTop
 ,ibot.value('@num', 'int') as abNum
 ,ibot.value('@batter', 'int') as batter
-- clip 

 ,ibotpit.value('@des', 'varchar(32)') as pitdesc
 ,ibotpit.value('@id', 'int') as seq
 ,ibotpit.value('@type', 'varchar(8)') as pittype
--clip

 from tblInnings i
       cross apply PBP.nodes('/inning') as inn(inn)
       cross apply inn.nodes('bottom/atbat') as ibot(ibot)
       cross apply ibot.nodes('pitch') as ibotpit(ibotpit)

1 个答案:

答案 0 :(得分:0)

如果您使用的是最新版本的SQL Server,则会有一种新的列数据类型(XML)。

您可以对其应用xpath,这使得查询列变得更加容易。

我建议您实际将XML存储为XML,而不是尝试将XML作为字符串存储在数据库中,而是将其视为XML。

有学习曲线。你需要熟悉XPATH,但这不是火箭科学。

一个例子:

SELECT Id, PartitionMonth, EmailAddress, AcquisitionCodeId, FieldValues.value('
declare namespace s="http://domain.com/FieldValues.xsd";
data(/s:FieldValues/s:item/@value)[1]', 'varchar(200)')
FROM Leads.Leads WITH (NOLOCK)
 WHERE Id = 190708

按键检索值的另一个示例:

SELECT r.EmailAddress, ar.Ip, ar.DateLog, 
  ar.FieldValues.value('
  declare namespace s="http://domain.com/FieldValues.xsd";
  data(/s:FieldValues/s:item[@key="First Name"]/@value)[1]', 'varchar(20)') FirstName,
  ar.FieldValues.value('
  declare namespace s="http://domain.com/FieldValues.xsd";
  data(/s:FieldValues/s:item[@key="Last Name"]/@value)[1]', 'varchar(20)') LastName
FROM Records.Records r WITH (NOLOCK)
JOIN Records.AcquisitionRecords ar WITH (NOLOCK) ON r.Id = ar.Id
WHERE ar.AcquisitionCodeId IN (19, 21, 30, 34, 36)
AND ar.DateLog BETWEEN '1-mar-09' AND '31-mar-09'

在SQL Server中开始使用XML的好地方 http://msdn.microsoft.com/en-US/library/ms189887(v=sql.90).aspx