我们有一个包含text
数据类型的xml数据的列。我的查询有大约10个连接。我想优化查询。以下是案例陈述。有没有更好的方法来查询xml节点,以便我们可以提高该查询的性能?
假设表名是XYZ。使用SQL Server 2005/2008
CASE
WHEN CONVERT(xml,CAST(XYX as nvarchar(MAX))).value('count(//CurrentStudents)','nvarchar(max)')=1
THEN 'All Students'
WHEN CONVERT(xml,CAST(XYZ as nvarchar(MAX))).value('count(//CurrentStudents/Value)','nvarchar(max)') = 0 AND CONVERT(xml, CAST(XYZ as nvarchar(MAX))).value('(//previousStudent/Value/text())[1]','nvarchar(max)') LIKE '%Studied Before%' OR CONVERT(xml,CAST(XYZ as nvarchar(MAX))).value('(//previousStudent/Value/text())[1]','nvarchar(max)') LIKE '%Studied Before but transferred%' OR CONVERT(xml,CAST(XYZ as nvarchar(MAX))).value('(//previousStudent/Value/text())[1]','nvarchar(max)') LIKE '%Have taken admission but didnt study%'
THEN 'Some Students'
WHEN CONVERT(xml,CAST(XYZ as nvarchar(MAX))).value('count(//CurrentStudents/Value)', 'nvarchar(max)') = 0 AND CONVERT(xml, CAST(XYZ as nvarchar(MAX))).value('count(//CurrentStudents)','nvarchar(max)') = 0 AND CONVERT(xml,CAST(XYZ as nvarchar(MAX))).value('count(//previousStudent)','nvarchar(max)') = 0
THEN 'No Students'
ELSE
'Bla Bla'
END
还有如何在此查询中添加DISTINCT。当我尝试它时会抛出错误,说xml数据不能用作不同的。
答案 0 :(得分:1)
有没有更好的方法来查询xml节点,以便我们可以提高该查询的性能?
由于您的数据以文本格式存储,因此您应该使用字符串解析函数(例如PATINDEX)而不是xml函数来避免不必要的转换。在罗马的时候......
如果必须使用xml函数,请创建一个子查询以进行一次转换,并多次使用转换后的值。 DRY ...
SELECT sub.myXml.value(....
(
SELECT CONVERT(xml,CAST(XYX as nvarchar(MAX))) myXml
FROM ...
) as sub
答案 1 :(得分:1)
使用distinct获得的错误不在此case语句中。您正在返回XML列的列。
当您执行此.value('count(//CurrentStudents)','nvarchar(max)')
之类的计数查询时,您可以使用数据类型int
来避免隐式转换为int .value('count(//CurrentStudents)','int')
。
扩展整个路径而不是使用//
更有效。将//CurrentStudents
更改为'/ SomeRoot / itemWhatever / CurrentStudents'。如果CurrentStudents
的所有节点都位于XML中的相同位置,则这是可行的。
您要多次查询相同的值。使用cross apply
可以避免这种情况。您还可以使用cross apply
来避免多次将文本列转换为XML。像这样的东西。
declare @T table(XMLCol text)
insert into @T values ('<root><i></i><i></i><i></i></root>')
select R.N
from @T
cross apply (select cast(cast(XMLCol as varchar(max)) as xml)) as X(Col)
cross apply (select X.Col.query('count(/root/i)').value('.', 'int')) as R(N)
如果您可以将表更改为保留XML列,那也会更好。这对性能和一致性都有好处。没有列中无效XML的风险。