背景:
今天遇到了數據合並和拆分的問題,嘗試了幾種寫法。但大致可分為兩類:一、原始寫法。二、Sql Server 2005之后支持的寫法。第一種寫法復雜而且效率低下,不推薦。所以下面具體講一下第二種寫法。
數據的拆分:
再講拆分前,首先先介紹兩個函數:cross apply和outer apply。這兩個函數作用是交叉連接。這兩個函數是在sql server 2005之后才有的,在2000與之相似的功能是cross join。雖然相似,但是cross join有一個致命功能缺陷。詳看代碼:
SELECT * FROM TEST01 AS T01 CROSS JOIN FUNC_TB2(T01.FIELD1) --FUNC_TB2為表值函數
執行此sql后,將報錯。詳細錯誤信息,如下:Msg 4104, Level 16, State 1, Line 1.The multi-part identifier "T01.FIELD1" could not be bound。由此可見,cross join不能接受由TEST01傳過去的值。由於cross join這樣的缺陷,所以sql server 在2005版本后新增了cross apply和outer apply,二者可以完全彌補這一缺陷。cross apply雖然與outer apply功能相似,但是二者也有不同。cross apply與FUNC_TB2交集的結果將去除右邊NULL項,而outer apply將包括NULL項。
上面,我們具體講了兩個函數的具體用法,下面講一下根據以上函數如何進行拆分。現有這樣一個Case:有一張表aaa,如圖所示
,現需要將name字段中的數據拆分出來。面對這樣的case我們兩步做。第一步,需要分割字符串;第二步,和id進行關聯。通過以上指導方針形成兩種sql語句。

SELECT id ,t02.item FROM dbo.aaa AS t01 CROSS apply dbo.Split(t01.name,',') AS t02 --dbo.Split為自定義的字符串分割函數,這個可以自己定義

SELECT tb01.id ,tb02.VALUE FROM( SELECT id ,[value] = CONVERT(xml,'<root><v>' + REPLACE(name, ',', '</v><v>') + '</v></root>') FROM dbo.aaa ) AS tb01 OUTER APPLY( SELECT VALUE = N.v.VALUE('.', 'varchar(100)') FROM tb01.[value].nodes('/root/v' ) N(v) ) AS tb02
執行結果如圖所示:
數據的合並:
在2005版本出來之前,數據合並是一件很麻煩的事情而且效率低下。現在具體講一下05之后的具體做法,即通過xml操作執行。Case如下:現有一張表bbb,如圖所示:
現需要將其進行Group by id進行數據合並,怎么做?
具體的sql如下:

SELECT id ,stuff(( SELECT ','+CLASS FROM dbo.bbb AS tb01 where tb01.id=tb02.id FOR xml PATH('')),1,1,'') AS classList FROM dbo.bbb AS tb02 GROUP BY id
結果如下:
本文來自:fang_beny (轉載請注明出處)