将两列的表连接成一个包含2个分隔符的字符串

时间:2016-10-05 22:08:23

标签: tsql

我们说我有一个包含两列的表格:

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来优雅地完成它,并且希望没有游标循环。

1 个答案:

答案 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>

更新2只是为了好玩:最小输出

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)