将逗号分隔字符串转为单列表格的T-SQL实现问题
将逗号分隔字符串转为单列表格的T-SQL实现问题
嗨,我完全懂你的困惑——有时候要把一堆逗号分隔的字符串转成单列表格确实容易绕晕,尤其是之前试了 pivot 没得到预期结果对吧?别担心,咱们来一步步搞定这个需求。
首先明确核心需求:你有好几行逗号分隔的字符串,要把每个逗号分隔的项(比如test_01、test_02)都变成临时表的单独一行,形成一个单列表。
方法一:用SQL Server 2016+自带的STRING_SPLIT函数
这个方法最简单,适合新版本的SQL Server:
第一步,先把你的原始多行字符串存到一个临时表(或者变量)里:
-- 创建临时表存储原始的逗号分隔字符串 CREATE TABLE #RawInput (RawString NVARCHAR(MAX)) -- 插入你提供的所有数据行 INSERT INTO #RawInput (RawString) VALUES ('test_01,test_02,test_03,test_04,test_05,test_06,test_07,test_08'), ('test_09,test_10,test_11,test_12,test_13,test_14,test_15,test_16'), ('test_17,test_18,test_19,test_20,test_21,test_22,test_23,test_24'), ('test_25,test_26,test_27,test_28,test_29,test_30,test_31,test_32'), ('test_33,test_34,test_35,test_36,test_37,test_38,test_39,test_40')
第二步,拆分字符串并生成目标单列表临时表:
-- 创建存储最终结果的临时表 CREATE TABLE #SingleColumnResult (ItemName NVARCHAR(100)) -- 用CROSS APPLY配合STRING_SPLIT拆分每一行的字符串,插入到结果表 INSERT INTO #SingleColumnResult (ItemName) SELECT SplitItem.Value FROM #RawInput ri CROSS APPLY STRING_SPLIT(ri.RawString, ',') SplitItem -- 查看最终结果 SELECT * FROM #SingleColumnResult
这里的关键是CROSS APPLY,它能把每一行的字符串拆分成多个行,再合并到结果表里,正好满足你的需求。你之前用pivot其实搞反了——pivot是把行转成列,而咱们需要的是把逗号分隔的“列项”转成行,所以拆分函数才是正确的方向。
方法二:适用于SQL Server 2016之前的版本(自定义拆分函数)
如果你的SQL Server版本比较旧,没有STRING_SPLIT,可以自己写一个拆分函数:
-- 自定义字符串拆分函数 CREATE FUNCTION dbo.SplitCommaString ( @InputString NVARCHAR(MAX), @Delimiter CHAR(1) = ',' ) RETURNS @SplitResults TABLE (Item NVARCHAR(100)) AS BEGIN DECLARE @StartPos INT = 1, @EndPos INT -- 确保字符串末尾有分隔符,避免漏拆最后一项 IF RIGHT(@InputString, 1) <> @Delimiter SET @InputString = @InputString + @Delimiter WHILE CHARINDEX(@Delimiter, @InputString) > 0 BEGIN SET @EndPos = CHARINDEX(@Delimiter, @InputString) -- 截取分隔符之间的内容插入结果表 INSERT INTO @SplitResults(Item) SELECT SUBSTRING(@InputString, @StartPos, @EndPos - @StartPos) -- 截断已处理的部分,继续循环 SET @InputString = SUBSTRING(@InputString, @EndPos + 1, LEN(@InputString)) END RETURN END GO
然后用法和上面类似,只需要把STRING_SPLIT换成自定义函数:
INSERT INTO #SingleColumnResult (ItemName) SELECT SplitItem.Item FROM #RawInput ri CROSS APPLY dbo.SplitCommaString(ri.RawString, ',') SplitItem
这样就能得到你想要的单列表临时表啦,所有test_xx都会单独占一行。
备注:内容来源于stack exchange,提问作者Alsjka




