1

我在 MyTable 中有以下表格行:

MessageID EMailAddress      DisplayName RecipientType
1         joe@email.com     Joe         To
1,        Bob@email.com     Max         From
1,        Max@email.com     NULL        To
1,        Secret@email.com  Secret      Bcc

我正在尝试将其转换为如下所示的 XML:

<to>
   <displayName>Joe</displayName>
   <address>joe@email.com</address>
</to>
<from>
   <displayName>Bob</displayName>
   <address>Bob@email.com</address>
</from>
<to>
   <address>Max@email.com</address>
</to>
<bcc>
   <displayName>Secret</displayName>
   <address>Secret@email.com</address>
</bcc>

我很接近,但无法弄清楚如何将 RecipientType 转换为其他两列的父元素

SELECT 
a.EmailAddress as address, 
a.DisplayName as displayName
FROM MyTable a
WHERE a.Id = 1
FOR XML PATH('address'), TYPE 

有没有办法让“FOR XML PATH('address')”成为 RecipientType 而不是硬编码的“address”?或者还有其他选择吗?

我也尝试过使用 PIVOT,但似乎没有帮助。

我知道我可以使用动态 SQL,但我试图远离它。

4

2 回答 2

1
with data as (
    select * from (
    values (1, 'joe@email.com', 'Joe', 'To', 1),
            (1, 'Bob@email.com', 'Bob', 'From', 2),
            (1, 'Max@email.com', null, 'To', 3),
            (1, 'Secret@email.com', 'Secret', 'Bcc', 4)
    ) t(MessageID, EMailAddress, DisplayName, RecipientType, Ordering)
    where MessageID = 1
), pivoted as (
    select *
    from data pivot (max(EmailAddress) for RecipientType in ([To], [From], [Bcc])) t
)
select (case when [To] is not null then DisplayName else null end) as 'to/displayName', [To] as 'to/address',
        (case when [From] is not null then DisplayName else null end) as 'from/displayName', [From] as 'from/address',
        (case when [Bcc] is not null then DisplayName else null end) as 'bcc/displayName', [Bcc] as 'bcc/address'
from pivoted
order by Ordering
for xml path('')
于 2013-04-10T15:28:55.453 回答
0

也许这可以让你开始:我认为你将需要一个元素,无论如何。

DECLARE @data XML;

SET @data = 

N'
<root>
<to>
   <displayName>Joe</displayName>
   <address>joe@email.com</address>
</to>
<from>
   <displayName>Bob</displayName>
   <address>Bob@email.com</address>
</from>
<to>
   <address>Max@email.com</address>
</to>
<bcc>
   <displayName>Secret</displayName>
   <address>Secret@email.com</address>
</bcc>
</root>';




SELECT 
      T.myAlias.value('(.)[1]', 'VARCHAR(32)') AS emailAddress
    , T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') as t
FROM 
    @data.nodes('//address') AS T(myAlias)
where
    T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') = 'to'
;

结果:

emailAddress                     t
-------------------------------- --------------------------------------------------
joe@email.com                    to
Max@email.com                    to

SELECT

      T.myAlias.value('(.)[1]', 'VARCHAR(32)') AS emailAddress
    , T.myAlias.value('(../displayName)[1]', 'VARCHAR(32)') AS displayName
    , T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') as RecipientType
FROM 
    @data.nodes('//address') AS T(myAlias)

;


emailAddress                     displayName                      RecipientType
-------------------------------- -------------------------------- 
joe@email.com                    Joe                              to
Bob@email.com                    Bob                              from
Max@email.com                    NULL                             to
Secret@email.com                 Secret                           bcc

除了身份证,什么都有。

Xml Shredding 不完全支持一个问题,position()。:<

http://connect.microsoft.com/SQLServer/feedback/details/383888/fully-support-position-in-xquery

在这篇文章中也可以看到:

在 SQL Server 的 XML 文档中查找节点顺序

于 2013-04-10T15:03:18.237 回答