1. 程式人生 > >利用 T-sql 的從句 for xml path('') 實現多行合併到一行, 並帶有分隔符

利用 T-sql 的從句 for xml path('') 實現多行合併到一行, 並帶有分隔符

T-sql 有一個for xml path('')的從句能把多行結果合併到一行,併成為xml 格式

比如有一張表tb有兩列,其格式和資料為:

id value
—————
1 aa
1 bb
2 aaa
2 bbb
2 ccc

如果對其執行sql: 

select id, value from tb for xml path('tbnode')

則返回的結果集僅為一行一列:

<tbnode><id>1</id><value>aa</value><id>1</id><value>bb</value>........<id>2</id><value>ccc</value></tbnode>

現在我們取巧一點, 省略path括號裡的內容, 同時把這兩列想辦法變成匿名列,sql如下:

select id+'',value+'' from tb for xml path('')
那麼返回結果如下(也是一個一行一列):

1aa1bb2aaa2bbb2ccc

基於這樣的思路, 現在要對所有不同的ID的value進行合併,希望得到如下的結果集:

id value
—————
1 aa,bb
2 aaa,bbb,ccc


首先我們來構造右邊一列:

sql如下:

select value+',' from tb where ID=1 for xml path('')

這樣就可以得到 "aa,bb," 。但是最後面會多一個逗號,可以在外面再套一層select,並利用SUBSTRING()函式來去掉它。 在網上的其他方法中也有把逗號加在value前,然後用stuff函式來去掉最前面多餘的逗號的,詳見參考連結。substring的缺點是用len函式的時候還要再填一遍“select value+',' from tb where ID=1 for xml path('')“,會顯得冗長。

最後完整的sql如下:

select id,
valuelist=substring((select value+',' from tb where tb.id=a.id for xml path('')),
1,
len((select value+',' from tb as b where b.id=a.id for xml path('')))-1) 
from tb as a 
group by id

或者用stuff:
select id,valuelist=stuff((select ','+value from tb as b where b.ID=a.ID for xml path('')),1,1,'') 
from tb as a 
group by id

參考連結: http://www.cnblogs.com/WindBlog/archive/2011/07/06/2099219.html

轉者注: 

for xml path('') 返回型別為nvarchar(max)