后面将主要讲我个人在实际开发中和网上看到的一些实例,希望拍砖。
SQL2005 利用XML合并聚合列
- 1. 合并
在平常的sql處理中,經常會碰到如下的情形,
有一個table T (id int, name varchar(10))
图片1
需要呈現的結果是,按照id相同的,把name值串起來,結果如下:
图片2
由於sql server并沒有提供字串的合并函數,所以需要特別處理,在SQL2000中,處理的方式一般有三種:cursor合并,function合并,臨時表合并。
A.Cursor合并:我們不提倡在普通的sql statement中使用cursor,所以一般不考慮這種方式。
B. Function合并:這在SQL2000中,是最常用的方式。、
图片3
C. 臨時表合并 :此種方式一般被使用在store procedure中,由於function本身的performance并不高,所以當遇到table數據較大時,常采用此種方式。
图片4
到了SQL2005 ,由於提供了outer apply 和對XML的良好支持,可以利用XML來簡單的處理合并字串的方式。
先來看一下,簡單的FOR XML出來的結果:
图片5
顯然上述結果是很吸引人的,因為它將本來3條記錄的結果,合并成1條了。如果再將上面的字串結果,利用replace,stuff等sql提供的函數來處理一下,是不是更吸引人呢?
图片6
上述結果,達到了合并字串的目的(只針對id=1), 接下來,就需要用到outer apply 來針對table里所有的id,一次全部合并name欄位了。
图片7
拆分:
1 --SQL2000的例子
2 Create table T(name nvarchar(50),amount int)
3 insert into T
4 select 'a,b,c' ,1
5 union all select 'd,f',2
6 union all select 'g',3
7 GO
8
9 SELECT
10 SUBSTRING(A.name,B.number,CHARINDEX(',',A.name+',',B.number)-B.number)AS [name],
11 amount
12 FROM T as A
13 JOIN master.dbo.spt_values AS B
14 ON B.type='p' AND B.number BETWEEN 1 AND LEN(A.name)
15 AND SUBSTRING(','+A.name,B.number,1)=','
16
17 /*
18 name amount
19 -------------------------------------------------- -----------
20 a 1
21 b 1
22 c 1
23 d 2
24 f 2
25 g 3
26 */
27
28 Drop table T
29
30
31 --SQL2005的例子
32 create table tb(id int,value varchar(30))
33 insert into tb values(1,'aa,bb')
34 insert into tb values(2,'aaa,bbb,ccc')
35 go
36 SELECT A.id, B.value
37 FROM(
38 SELECT id, [value] = CONVERT(xml,'<root><v>' + REPLACE([value], ',','</v><v>') + '</v></root>') FROM tb
39 )A
40 OUTER APPLY(
41 SELECT value = N.v.value('.', 'varchar(100)') FROMA.[value].nodes('/root/v') N(v)
42 )B
43
44 DROP TABLE tb
45
46 /*
47 id value
48 ----------- ------------------------------
49 1 aa
50 1 bb
51 2 aaa
52 2 bbb
53 2 ccc
54
55 (5 行受影响)
56 */
57