我在数据库列中包含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 ..... .... .... ..... ... ...
感谢。
答案 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