有时候需要对多行数据进行合并,数值型的字段还好说,可以直接进行汇总计算。但字符串怎么办?
其实,在SQL Server 2008中,使用两个技巧即可实现上述需求。
1、一个强大的技巧,是使用For xml path('')来实现指定格式的字符输出。
For xml path的意思,就是将结果集,以xml的方式进行输出。因为可以定义结果中行和列的格式,所以可以通过指定字符进行格式化输出。
假设我们有表test:
id value
1 a
1 b
2 c
2 d
则select ’-' + value from test for xml path('')的结果为-a-b-c-d。
2、使用函数stuff,删除指定长度的字符并在指定的起始点插入另一组字符。
stuff的原型是:STUFF ( character_expression , start , length , character_expression )
参数说明:
character_expression:由字符数据组成的表达式。character_expression 可以是常量、变量,也可以是字符或二进制数据的列。
startIndex:整形值,指定删除和插入的开始位置。如果 start 或 length 是负数,则返回空字符串。如果 start 比第一个 character_expression 长,则返回空字符串。注意,startIndex总是从1开始的。
length:整数,指定要删除的字符数。如果 length 比第一个 character_expression 长,则最多删除到最后一个 character_expression 中的最后一个字符。
返回类型:如果 character_expression 是一个支持的字符数据类型,则返回字符数据。如果 character_expression 是一个支持的 binary 数据类型,则返回二进制数据。
为便于理解此函数,可以看下面这个例子:
SELECT STUFF('1234', 2, 3, '56789')。意思是删除从第二个字符开始的三个字符,然后把第二个字符串插入,因此结果是'156789'。
SELECT STUFF('12345', 2, 3, '56789')。结果是'1567895'。即第一个字符串删除掉234,插入'56789',再把'5'加上。
如何利用这两个原理来实现基于GroupBy的字符串拼接呢?
假如我们使用的字符串连接符是'-',首先使用for xml path实现格式化输出,然后再把第一个'-'再用空字符串替换掉,不就是得到结果了吗?即:
select id,value = stuff(select '-' + value from test as t where t.id = test.id for xml path('')), 1, 1, '')
from test
Group by id
即得到输出:
1 a-b
2 c-d