作項目的過程當中,遇到一個問題,相同id,不一樣value的記錄但願合併成一條記錄,value以逗號分隔,從網上搜了搜解決方案,整理以下,備忘。express
1、字符串合併ide
表名:test函數
字段:spa
idint.net
namenvarchar(50)blog
字段值:字符串
指望結果:it
idnameStrio
-----------------------------class
1a,b,c
2d,e
3f
SQL實現:
一、利用函數解決
-- 建立處理函數
CREATEFUNCTION dbo.f_str(@id int)
RETURNSvarchar(8000)
AS
BEGIN
DECLARE @r varchar(8000)
SET @r =''
SELECT @r = @r +','+ [name]
FROM [test]
WHERE [id]=@id
SET @r =STUFF(@r, 1, 1,'')
RETURN @r
END
GO
-- 調用函數
SELECT [id], [nameStr]=dbo.f_str(id)
FROM [test]
GROUPBY [id]
運行結果:
二、直接用SQL解決
SELECT*
FROM(
SELECTDISTINCT [id]
FROM [test]
)A
OUTERAPPLY(
SELECT
[nameStr]=STUFF(REPLACE(REPLACE(
(
SELECT [name] FROM [test] N
WHERE [id] = A.id
FORXMLAUTO
),'<N name="',','),'"/>',''), 1, 1,'')
)M
運行結果:
看不懂這個SQL沒關係,下面有詳細分析
2、詳細分析
一、STUFF
做用:
STUFF函數將字符串插入另外一字符串。它在第一個字符串中從開始位置刪
除指定長度的字符;而後將第二個字符串插入第一個字符串的開始位置。
語法:
STUFF ( character_expression , start , length ,character_expression )
參數:
character_expression
一個字符數據表達式。character_expression能夠是常量、變量,也可
以是字符列或二進制數據列。
start
一個整數值,指定刪除和插入的開始位置。若是start或length爲負,
則返回空字符串。若是start比第一個character_expression長,則返
回空字符串。start能夠是bigint類型。
length
一個整數,指定要刪除的字符數。若是length比第一個
character_expression長,則最多刪除到第一個character_expression
中的最後一個字符。Length能夠是bigint類型。
返回類型:
若是character_expression是受支持的字符數據類型,則返回字符數據。
若是character_expression是一個受支持的 binary 數據類型,則返回二
進制數據。
註釋:
若是開始位置或長度值是負數,或者若是開始位置大於第一個字符串的長
度,將返回空字符串。若是要刪除的長度大於第一個字符串的長度,將刪
除到第一個字符串中的最後一個字符。若是結果值大於返回類型支持的最
大值,則產生錯誤。
示例:
SELECTSTUFF('abcdef', 2, 3,'ijklmn');
GO
結果:
SELECTSTUFF('abcdef',-2, 3,'ijklmn');
GO
結果:
SELECTSTUFF('abcdef', 2, 10,'ijklmn');
GO
結果:
二、CROSS APPLY 與OUTERAPPLY
使用 APPLY 運算符能夠爲實現查詢操做的外部表表達式返回的每一個行調用表值函數。表值函數做爲右輸入,外部表表達式做爲左輸入。經過對右輸入求值來得到左輸入每一行的計算結果,生成的行被組合起來做爲最終輸出。APPLY 運算符生成的列的列表是左輸入中的列集,後跟右輸入返回的列的列表。
APPLY 有兩種形式:CROSS APPLY 和 OUTER APPLY。CROSS APPLY 僅返回外部表中經過表值函數生成結果集的行。OUTER APPLY 既返回生成結果集的行,也返回不生成結果集的行,其中表值函數生成的列中的值爲 NULL。
用示例來區分二者:
第一張表:
表名:student
字段名:
字段值:
第二張表:
表名:student_class
字段名:
字段值:
CROSS APPLY
SELECT*
FROM [student] a
CROSSAPPLY(
SELECT [class], [score]
FROM [student_class]
WHERE student_id = a.id
) b
運行結果:
OUTERAPPLY
SELECT*
FROM [student] a
OUTERAPPLY(
SELECT [class], [score]
FROM [student_class]
WHERE student_id = a.id
) b
運行結果:
三、FORXMLAUTO
將結果轉換爲XML結構,例如對於上面2中的student表,執行如下語句
SELECT*
FROM [student]
FORXMLAUTO
運行結果:
其中FOR XML還有其餘方式:RAW、EXPLICIT和PATH,有興趣的同窗能夠深刻研究,這裏再也不贅述。
轉載至:http://blog.csdn.net/xiaomianao2010/article/details/6035634