我们说我有一个包含两列的表格:
create table #counties(
state varchar(max),
name varchar(max)
)
insert #counties(state,name) values('Alabama','Autauga')
insert #counties(state,name) values('Alabama','Baldwin')
insert #counties(state,name) values('Texas','Adams')
insert #counties(state,name) values('Texas','Houston')
insert #counties(state,name) values('Wisconsin','Adair')
insert #counties(state,name) values('Wisconsin','Wood')
我希望结果是这样的单个字符串:
Autauga;Baldwin^^Adams;Houston^^Adair;Wood
对于第一列中的每次更改,我都希望^^
分隔符,并且对于第二列中的每次更改,我都希望;
分隔符。
我知道coalesce
功能,但我无法弄清楚如何在两列上使用它,而不仅仅是一列:
declare @c varchar(max)
select @c = COALESCE(@c + ';', '') + name from #counties order by state, name
select @c
这仅适用于数据加载,但我仍然想学习如何只使用select来优雅地完成它,并且希望没有游标循环。
答案 0 :(得分:2)
尝试这样
With NamesPerState AS
(
SELECT c1.[state]
,STUFF(
(
SELECT ';' + c2.[name]
FROM #counties AS c2
WHERE c1.[state]=c2.[state]
ORDER BY c2.[name]
FOR XML PATH('')
),1,1,'') AS names
FROM #counties AS c1
GROUP BY c1.[state]
)
SELECT STUFF
(
(
SELECT '^^' + names
FROM NamesPerState
ORDER BY [state]
FOR XML PATH('')
),1,2,''
)
只是为了向您展示,采用干净和现代的方法是多么容易:
SELECT [state]
,
(
SELECT c2.[name]
FROM #counties AS c2
WHERE c1.[state]=c2.[state]
ORDER BY c2.[name]
FOR XML RAW('county'),TYPE
)
FROM #counties AS c1
GROUP BY c1.[state]
FOR XML RAW('state'),ROOT('counties')
结果
<counties>
<state state="Alabama">
<county name="Autauga" />
<county name="Baldwin" />
</state>
<state state="Texas">
<county name="Adams" />
<county name="Houston" />
</state>
<state state="Wisconsin">
<county name="Adair" />
<county name="Wood" />
</state>
</counties>
SELECT [state] AS [*]
,
(
SELECT c2.[name] AS [*]
FROM #counties AS c2
WHERE c1.[state]=c2.[state]
ORDER BY c2.[name]
FOR XML PATH('c'),TYPE
)
FROM #counties AS c1
GROUP BY c1.[state]
FOR XML PATH('s'),ROOT('counties')
结果
<counties>
<s>Alabama<c>Autauga</c><c>Baldwin</c></s>
<s>Texas<c>Adams</c><c>Houston</c></s>
<s>Wisconsin<c>Adair</c><c>Wood</c></s>
</counties>
这会让你的清单回复:
DECLARE @x XML=
'<counties>
<s>Alabama<c>Autauga</c><c>Baldwin</c></s>
<s>Texas<c>Adams</c><c>Houston</c></s>
<s>Wisconsin<c>Adair</c><c>Wood</c></s>
</counties>';
SELECT s.value('(text())[1]','nvarchar(max)') AS [state]
,c.value('.','nvarchar(max)') AS [name]
FROM @x.nodes('/counties/s') AS A(s)
OUTER APPLY s.nodes('c') AS B(c)