一、 字符串合並
表名:test
字段:
id int
name nvarchar(50)
字段值:
期望結果:
id nameStr
-----------------------------
1 a,b,c
2 d,e
3 f
SQL實現:
1、 利用函數解決
-- 創建處理函數
CREATE FUNCTION dbo.f_str(@id int)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @r varchar(8000)
SET @r = ''
SELECT @r = @r + ',' + [name]
FROM [test]
WHERE [id]=@id
RETURN STUFF(@r, 1, 1, '')
END
GO
-- 調用函數
SELECT [id], [nameStr]=dbo.f_str(id)
FROM [test]
GROUP BY [id]
運行結果:
2、 直接用SQL解決
SELECT *
FROM(
SELECT DISTINCT [id]
FROM [test]
)A
OUTER APPLY(
SELECT
[nameStr]= STUFF(REPLACE(REPLACE(
(
SELECT [name] FROM [test] N
WHERE [id] = A.id
FOR XML AUTO
), '<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 數據類型,則返回二
進制數據。
注釋:
如果開始位置或長度值是負數,或者如果開始位置大於第一個字符串的長
度,將返回空字符串。如果要刪除的長度大於第一個字符串的長度,將刪
除到第一個字符串中的最后一個字符。如果結果值大於返回類型支持的最
大值,則產生錯誤。
示例:
SELECT STUFF('abcdef', 2, 3, 'ijklmn');
GO
結果:
SELECT STUFF('abcdef', -2, 3, 'ijklmn');
GO
結果:
SELECT STUFF('abcdef', 2, 10, 'ijklmn');
GO
結果:
2、 CROSS APPLY 與 OUTER APPLY
使用 APPLY 運算符可以為實現查詢操作的外部表表達式返回的每個行調用表值函數。表值函數作為右輸入,外部表表達式作為左輸入。通過對右輸入求值來獲得左輸入每一行的計算結果,生成的行被組合起來作為最終輸出。APPLY 運算符生成的列的列表是左輸入中的列集,后跟右輸入返回的列的列表。
APPLY 有兩種形式:CROSS APPLY 和 OUTER APPLY。CROSS APPLY 僅返回外部表中通過表值函數生成結果集的行。OUTER APPLY 既返回生成結果集的行,也返回不生成結果集的行,其中表值函數生成的列中的值為NULL。
用示例來區分兩者:
第一張表:
表名:student
字段名:
字段值:
第二張表:
表名:student_class
字段名:
字段值:
CROSS APPLY
SELECT *
FROM [student] a
CROSS APPLY(
SELECT [class], [score]
FROM [student_class]
WHERE student_id = a.id
) b
運行結果:
OUTER APPLY
SELECT *
FROM [student] a
OUTER APPLY(
SELECT [class], [score]
FROM [student_class]
WHERE student_id = a.id
) b
運行結果:
3、 FOR XML AUTO
將結果轉換為XML結構,例如對於上面2中的student表,執行以下語句
SELECT *
FROM [student]
FOR XML AUTO
運行結果: