【问题标题】:Convert simple XML to Table in SQL在 SQL 中将简单的 XML 转换为表
【发布时间】:2015-05-03 15:55:56
【问题描述】:

我正在尝试将以下 XML 转换为表格。

DECLARE @XMLToParse  XML;
SET @XMLToParse =   '<Employees>
                        <Senior>
                            <Emp>
                                Ravi
                            </Emp>
                            <Emp>
                                Shanker
                            </Emp>
                            <Emp>
                                Aditya
                            </Emp>
                        </Senior>
                        <Junior>
                            <Emp>
                                Roy
                            </Emp>
                            <Emp>
                                Sham
                            </Emp>
                            <Emp>
                                Divya
                            </Emp>
                        </Junior>
                      </Employees>';


DECLARE @ParsingTable  TABLE
    (Senior VARCHAR(100),Junior VARCHAR(100))

INSERT
INTO    @ParsingTable
    (Senior)
SELECT  xmlData.A.value('.', 'VARCHAR(100)') AS Senior

FROM    @XMLToParse.nodes('Employees/Senior/Emp') as xmlData(A)

select * from @ParsingTable

我正在尝试创建如下所示的表格:

Senior     Junior
-----------------
Ravi       Roy
Shanker    Sham
Aditya     Divya

上面的代码给了我第一列,但我不知道如何插入第二列。

【问题讨论】:

  • 您有问题。当初级员工和高级员工的数量不同时会发生什么。该表应该是两列:等级(初级或高级),员工姓名。
  • @jdweng 这只是一个示例 xml。假设相同的编号。初级和高级 emp :)
  • 你不能做你想做的,因为你需要连接两个对象,并且没有唯一的方法来执行连接。

标签: sql asp.net sql-server stored-procedures


【解决方案1】:

我相信有很多方法可以通过使用cross apply 获得您想要的结果之一 方法1

DECLARE @ParsingTable  TABLE
    (Senior VARCHAR(100),Junior VARCHAR(100))

INSERT
INTO    @ParsingTable
    (Senior,Junior)
SELECT  A.value('.', 'VARCHAR(100)') AS Senior,
        B.value('.', 'VARCHAR(100)') AS Junior
FROM    @XMLToParse.nodes('Employees/Senior/Emp') as xmlDataSenior(A) CROSS APPLY
        @XMLToParse.nodes('Employees/Junior/Emp') as xmlDataJunior(B)

注意:这会给你重复记录

方法2: 从这种方法你只能得到一条记录......对于第一条记录[1],对于第二条记录[2],第三条记录[3]等等............

SELECT  
    @XMLToParse.value('(Employees/Senior/Emp/text())[1]','VARCHAR(100)') AS Senior,
    @XMLToParse.value('(Employees/Senior/Emp/text())[1]','VARCHAR(100)') AS Junior

METHOD3:你可以通过这个技巧得到你想要的结果

使用Row_Number 为高级和初级创建2 个通用表表达式,并通过第一个cte 的row_number 和第二个cte 加入这两个ctes 这是您的完整代码

     DECLARE @XMLToParse  XML;
     SET @XMLToParse =   '<Employees>
                        <Senior>
                            <Emp>
                                Ravi
                            </Emp>
                            <Emp>
                                Shanker
                            </Emp>
                            <Emp>
                                Aditya
                            </Emp>
                        </Senior>
                        <Junior>
                            <Emp>
                                Roy
                            </Emp>
                            <Emp>
                                Sham
                            </Emp>
                            <Emp>
                                Divya
                            </Emp>
                        </Junior>
                      </Employees>';


DECLARE @ParsingTable  TABLE
    (Senior VARCHAR(1000),Junior VARCHAR(100))


;with cte as
(
SELECT  A.value('.', 'VARCHAR(100)') AS Senior,
        ROW_NUMBER() OVER(ORDER BY  A.value('.', 'VARCHAR(100)') DESC) AS SeniorRowNo

FROM    @XMLToParse.nodes('Employees/Senior/Emp') as xmlDataSenior(A)
)

 , cte2 as
 ( 
        SELECT  B.value('.', 'VARCHAR(100)') AS Junior,
        ROW_NUMBER() OVER(ORDER BY  B.value('.', 'VARCHAR(1000)') DESC) AS JuniorRowNo
         FROM
        @XMLToParse.nodes('Employees/Junior/Emp') as xmlDataJunior(B)   
 )

 INSERT INTO    @ParsingTable(Senior,Junior)
 Select cte.Senior,cte2.Junior
 From cte inner join cte2 on cte.SeniorRowNo= cte2.JuniorRowNo
 select * from @ParsingTable

SQLFIDDLE METHOD 3

输出:

  Senior     Junior
-----------------
Shanker    Sham
Ravi       Roy
Aditya     Divya

【讨论】:

  • 但似乎这两种方法都没有给出完整的预期结果。
  • @iJade 查看我编辑的答案
  • @iJade Check SQL FIDDLE
【解决方案2】:

Pivot 在这里看起来是显而易见的事情,但它需要一些可能不太明显的 XML 查询才能获得可以进行透视的结果集。

select P.Senior, 
       P.Junior
from (
     select T1.X.value('local-name(.)', 'nvarchar(100)') as ColumnName,
            T3.Value,
            T3.RowID
     from @XMLToParse.nodes('/Employees/*') as T1(X)
       cross apply (
                   select T2.X.value('text()[1]', 'nvarchar(100)') as Value,
                          row_number() over(order by T2.X) as RowID
                   from T1.X.nodes('Emp') as T2(X)
                   ) as T3
     ) as T
pivot (max(T.Value) for T.ColumnName in (Senior, Junior)) as P

您透视的派生表如下所示:

ColumnName Value      RowID
---------- ---------- --------------------
Senior     Ravi       1
Senior     Shanker    2
Senior     Aditya     3
Junior     Roy        1
Junior     Sham       2
Junior     Divya      3

RowID 将行配对在一起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 2011-04-28
    • 1970-01-01
    • 2022-01-17
    • 2014-05-14
    • 2011-10-08
    相关资源
    最近更新 更多