根據某一字段值相同合併字符串 - - SQL
做項目的過程中,遇到一個問題,相同id,不同value的記錄希望合併成一條記錄,value以逗號分隔,從網上搜了搜解決方案,整理如下,備忘。
一、字符串合併
表名:test
字段:
id int
name nvarchar(50)
字段值:
期望結果:
id nameStr
-----------------------------
1 a,b,c
2 d,e
3 f
SQL實現:
1、利用函數解決
-- 創建處理函數
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
RETURNSTUFF(@r, 1, 1,'')
END
GO
-- 調用函數
SELECT [id], [nameStr]=dbo.f_str(id)
FROM [test]
GROUPBY [id]
運行結果:
2、直接用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不要緊,下面有詳細分析
二、詳細分析
1、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
結果:
2、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
運行結果:
3、FORXMLAUTO
將結果轉換爲XML結構,例如對於上面2中的student表,執行以下語句
SELECT*
FROM [student]
FORXMLAUTO
運行結果: