SQL查询XML多个节点一列

时间:2018-05-08 15:12:59

标签: xml sql-server-2008 tsql pivot

我在数据库列中包含XML,其中包含其他一些列:

RowID    PeopleXML
1        <people>2 people nodes</people>
2        <people>3 people nodes</people>

每个XML列的结构类似于

<people>
    <person Name="Aaron" Lastname="Man"></person>   
    <person Name="Barbara" Lastname="Woman"></person>
</people>

人们中没有固定数量的人员节点。可能没有或任何给定数量。

我想使用SQL Server进行查询。我需要一行中每个数据行的所有人。例如

RowID  name1  lastname1  name2    lastname2
1      Aaron  Man        Barbara  Woman
2      .....  ....       ....     .....     ...  ...

感谢。

1 个答案:

答案 0 :(得分:1)

你可以这样试试:

DECLARE @tbl TABLE(RowID INT IDENTITY,PeopleXML XML);
INSERT INTO @tbl VALUES
 (N'<people type="many people">
        <person Name="Aaron" Lastname="Man"></person>   
        <person Name="Barbara" Lastname="Woman"></person>
    </people>')
,(N'<people type="one person">
        <person Name="Lonely" Lastname="Boy"></person>   
    </people>')
,(N'<people type="nobdy">
    </people>')
,(NULL);

SELECT RowID
      ,PeopleXML.value(N'(/people/@type)[1]',N'nvarchar(max)') AS TypeDescription 
      ,pers.value(N'@Name',N'nvarchar(max)') AS PersonName
      ,pers.value(N'@Lastname',N'nvarchar(max)') AS PersonLastname
FROM @tbl
OUTER APPLY PeopleXML.nodes(N'/people/person') AS A(pers);

结果

RowID   TypeDescription PersonName  PersonLastname
1       many people     Aaron       Man
1       many people     Barbara     Woman
2       one person      Lonely      Boy
3       nobdy           NULL        NULL
4       NULL            NULL        NULL

如果要将结果缩小为CROSS APPLY的行,请使用<Person>

更新:透视

我刚看到,你需要在一行中得到结果...在大多数情况下,你不能做到最好...应该仅用于输出......

WITH Numbered AS
(
    SELECT RowID
          ,ROW_NUMBER() OVER(PARTITION BY RowID ORDER BY (SELECT NULL)) AS PersonIndex
          ,PeopleXML.value(N'(/people/@type)[1]',N'nvarchar(max)') AS TypeDescription 
          ,pers.value(N'@Name',N'nvarchar(max)') AS PersonName
          ,pers.value(N'@Lastname',N'nvarchar(max)') AS PersonLastname
    FROM @tbl
    OUTER APPLY PeopleXML.nodes(N'/people/person') AS A(pers)
)
SELECT RowID
      ,MAX(CASE WHEN PersonIndex=1 THEN PersonName END) AS Nm1
      ,MAX(CASE WHEN PersonIndex=1 THEN PersonLastname END) AS LNm1
      --second person
      ,MAX(CASE WHEN PersonIndex=2 THEN PersonName END) AS Nm2
      ,MAX(CASE WHEN PersonIndex=2 THEN PersonLastname END) AS LNm2
      --add as many as you need
FROM Numbered 
GROUP BY RowID;

结果

    Nm1    LNm1     Nm2     LNm2
1   Aaron   Man     Barbara Woman
2   Lonely  Boy     NULL    NULL
3   NULL    NULL    NULL    NULL
4   NULL    NULL    NULL    NULL