样本数据
下次请提供文字而不是图片;-)
列Markets 定义为nvarchar(max)。数据以 unicode 形式插入(带有 N 前缀)。
create table Company2
(
Code nvarchar(6),
Name nvarchar(11),
Markets nvarchar(max),
Phone nvarchar(12)
);
insert into Company2 (Code, Name, Markets, Phone) values
(N'ABC123',
N'JOHN DEERE',
N'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<license>
<company companyCode="ABC123">
<markets>
<market marketCode="AA"/>
<market marketCode="BB"/>
<market marketCode="CC"/>
<market marketCode="DD"/>
</markets>
</company>
</license>',
N'555-123-0000'),
(N'DEF456',
N'NEW HOLLAND',
N'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<license>
<company companyCode="DEF456">
<markets>
<market marketCode="AA"/>
<market marketCode="FF"/>
<market marketCode="GG"/>
<market marketCode="HH"/>
<market marketCode="KK"/>
</markets>
</company>
</license>',
N'555-456-0000');
解决方案
无法将Markets 直接转换为XML,因为nvarchar(max) 编码与数据中的“utf-8”冲突。我将转换移动到一个单独的公用表表达式(CTE,cte_convert),从nvarchar(max) 到varchar(max) 到XML。
下一个 CTE (cte_parse) 现在可以使用 c.MarketsXML.nodes() 将 XML 中的 <market> 节点提取到新列 m.Market 中。从该列中提取@marketCode 属性作为所需值。
然后使用带有for xml path('') 的子查询来连接这些值。
with cte_convert as
(
select c.Code, c.Name, convert(XML, convert(varchar(max), c.Markets)) as MarketsXML, c.Phone
from Company2 c
),
cte_parse as
(
select c.Code, c.Name, m.Market.value('@marketCode', 'nvarchar(10)') as MarketCode, c.Phone
from cte_convert c
outer apply c.MarketsXML.nodes('/license/company/markets/market') as m(Market)
)
select cp.Code,
cp.Name,
stuff(( select ',' + cp2.MarketCode as MC
from cte_parse cp2
where cp2.Code = cp.Code
for xml path(''), type).value('.', 'nvarchar(max)'),1,1,'') as MarketCodes,
cp.Phone
from cte_parse cp
group by cp.Code, cp.Name, cp.Phone;
结果
Code Name MarketCodes Phone
------ ----------- -------------- ------------
ABC123 JOHN DEERE AA,BB,CC,DD 555-123-0000
DEF456 NEW HOLLAND AA,FF,GG,HH,KK 555-456-0000
此原始解决方案使用从 SQL Server 2017 开始可用的 string_agg() 函数。
样本数据
备注:Markets 列定义为XML 以反映其内容。
create table Company
(
Code nvarchar(6),
Name nvarchar(11),
Markets XML,
Phone nvarchar(12)
);
insert into Company (Code, Name, Markets, Phone) values
('ABC123',
'JOHN DEERE',
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<license>
<company companyCode="ABC123">
<markets>
<market marketCode="AA"/>
<market marketCode="BB"/>
<market marketCode="CC"/>
<market marketCode="DD"/>
</markets>
</company>
</license>',
'555-123-0000'),
('DEF456',
'NEW HOLLAND',
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<license>
<company companyCode="DEF456">
<markets>
<market marketCode="AA"/>
<market marketCode="FF"/>
<market marketCode="GG"/>
<market marketCode="HH"/>
<market marketCode="KK"/>
</markets>
</company>
</license>',
'555-456-0000');
解决方案
with cte_parse as
(
select c.Code, c.Name, m.Market.value('@marketCode', 'nvarchar(10)') as MarketCode, c.Phone
from Company c
outer apply c.Markets.nodes('/license/company/markets/market') as m(Market)
)
select cp.Code, cp.Name, string_agg(cp.MarketCode, ',') as MarketCodes, cp.Phone
from cte_parse cp
group by cp.Code, cp.Name, cp.Phone;
Fiddle