要使用任何(,)分隔符在单个列中检索的XML值

时间:2017-06-07 08:15:27

标签: sql-server xml tsql xpath xquery

我的Xml文件

<Detials xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Tests>
  <Test Name="Test1" TotalMarks="100">95</Test>
  <Test Name="Test2" TotalMarks="200">65</Test>
  <Test Name="Test3" TotalMarks="150">95</Test>
  <Test Name="Test4" TotalMarks="150"></Test>
    </Tests>
</Detials>

我想将其查询为

TestName         |TotalMarks     |ScoreObtained** 
Test1,Test2,Test3,Test4|100,200,150,150| 95,65,95,|

我尝试了这个,但是无法按照我的意愿获得上面的结果,我得到了错误 XQuery [T1.XMLData.query()]:“)”是预期的。

Select 

                           TestName  = x.c.query ('STUFF((SELECT 
              '','' + fd.v.value(''(.)[1]'', ''varchar(100)'')
           FROM 
              XMLwithOpenXML
           CROSS APPLY
              XMLData.nodes(''/Tests/Test/@Name'') AS fd(v)
           FOR XML PATH('''')
          ), 1, 1, ''''') 


                        From T1 s
                        Cross Apply s.XMLData.nodes('/Detials') AS x(c)

帮我解决这个问题!

谢谢,Jayendran

2 个答案:

答案 0 :(得分:1)

  

&#39; TestName = x.c.query(&#39; STUFF((SELECT ...&#39;

您试图在<{1}}表达式中添加&#39; T-SQL&#39; -statement <...> ...这无效......

这种做法似乎很危险......

使用给定的示例,最后一个条目加倍。您的预期输出显示三个值为XQuery,但四个值为TestName,四个值(末尾为空值)为TotalMarks。你的方法在我看来非常危险......如果有两个&#34; Test1&#34;项?你不知道ScoreObtained是属于这个,还是属于#34; Test2&#34;。这真的是你需要的输出吗?

可能的解决方案

你可以试试这个,但我真的怀疑,你的方法是正确的:

TotalMarks="200"

结果

DECLARE @xml XML=
'<Detials xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Tests>
  <Test Name="Test1" TotalMarks="100">95</Test>
  <Test Name="Test2" TotalMarks="200">65</Test>
  <Test Name="Test3" TotalMarks="150">95</Test>
  <Test Name="Test3" TotalMarks="150"></Test>
    </Tests>
</Detials>';

WITH DerivedTable AS
(
    SELECT t.value(N'@Name','nvarchar(max)') AS Name
          ,t.value(N'@TotalMarks','nvarchar(max)') AS Mark
          ,t.value(N'.','nvarchar(max)') AS Point --use 'text()[1]' to avoid empty values
    FROM @xml.nodes(N'/Detials/Tests/Test') AS A(t)
)
SELECT
    (
        STUFF(
        (
        SELECT ', ' + Name FROM DerivedTable GROUP BY Name ORDER BY Name FOR XML PATH(''),TYPE
        ).value(N'text()[1]','nvarchar(max)'),1,2,'')
    ) AS TestName
   ,(
        STUFF(
        (
        SELECT ', ' + Mark FROM DerivedTable ORDER BY Name FOR XML PATH(''),TYPE
        ).value(N'text()[1]','nvarchar(max)'),1,2,'')
    ) AS TotalMarks
   ,(
        STUFF(
        (
        SELECT ', ' + Point FROM DerivedTable ORDER BY Name FOR XML PATH(''),TYPE
        ).value(N'text()[1]','nvarchar(max)'),1,2,'')
    ) AS ScoreObtained;

答案 1 :(得分:1)

SELECT STUFF(@x.query('for $a in (*:Detials/Tests/Test/@Name) return <a>{concat(",", $a)}</a>').value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS ListOfName
SELECT STUFF(@x.query('for $a in (*:Detials/Tests/Test/@TotalMarks) return <a>{concat(",", $a)}</a>').value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS ListOfTotalMarks
SELECT STUFF(@x.query('for $a in (*:Detials/Tests/Test) return <a>{concat(",", $a)}</a>').value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS ListOfInnerHTML

<强> Demo

注意:第一个SELECT的格式如下:

SELECT STUFF(
    @x.query('for $a in (*:Detials/Tests/Test/@Name) 
        return <a>{concat(",", $a)}</a>')
    .value('.', 'NVARCHAR(MAX)'), 
    1, 1, '') AS ListOfName