我有以下三个不同的字符串,需要分成三个不同的列。
示例:
字符串1:
Declare @str1 varchar(max) = 'A1,A2,A3'
字符串2:
Declare @str2 varchar(max) = 'B1,B2,B3'
字符串3:
Declare @str2 varchar(max) = 'C1,C2,C3'
注意我想将上述三个字符串存储在三个不同的列中。
预期输出:
colA colB colC
------------------
A1 B1 C1
A2 B2 C2
A3 B3 C3
答案 0 :(得分:2)
我知道它有点重,但它会起作用
Declare @str1 varchar(max) = 'A1,A2,A3'
Declare @str2 varchar(max) = 'B1,B2,B3'
Declare @str3 varchar(max) = 'C1,C2,C3'
DECLARE @RowCount TINYINT
DECLARE @i TINYINT = 0
DECLARE @Table AS TABLE
(
colA varchar(MAX)
,ColB varchar(MAX)
,ColC varchar(MAX)
)
SET @RowCount = len(@str1) - len(replace(@str1, ',', ''))
WHILE(@i<=@RowCount)
BEGIN
INSERT INTO @Table
SELECT LEFT(@str1,CHARINDEX(',',@str1+',',0)-1) AS colA
,LEFT(@str2,CHARINDEX(',',@str2+',',0)-1) AS colB
,LEFT(@str3,CHARINDEX(',',@str3+',',0)-1) AS colC
SET @str1 = STUFF(@str1,1,CHARINDEX(',',@str1,0),'')
SET @str2 = STUFF(@str2,1,CHARINDEX(',',@str2,0),'')
SET @str3 = STUFF(@str3,1,CHARINDEX(',',@str3,0),'')
SET @i = @i + 1
END
SELECT * FROM @Table
答案 1 :(得分:0)
如果你有三个值,那么试试这个。
DECLARE @str1 VARCHAR(max) = 'A1,A2,A3'
SELECT Parsename(Replace(@str1, ',', '.'), 3) 'FST_COL',
Parsename(Replace(@str1, ',', '.'), 2) 'SCD_COL',
Parsename(Replace(@str1, ',', '.'), 1) 'TRD_COL' into #temp
或
DECLARE @str1 VARCHAR(max) = 'A1,A2,A3',
@sql NVARCHAR(max),
@loop INT,
@cnt INT=1
SELECT @loop = Len(@str1) - Len(Replace(@str1, ',', '')) + 1
SET @sql=' WITH Split_cols ( xmlcol)
AS (SELECT CONVERT(XML, ''<cols><col>''
+ Replace('''
+ @str1 + ''', '','', ''</col><col>'') + ''</col></cols>'') as xmlcol)
SELECT '
WHILE @cnt <= @loop
BEGIN
SET @sql+=' xmlcol.value(''/cols[1]/col['
+ CONVERT(VARCHAR(30), @cnt)
+ ']'', ''varchar(100)'') AS col'
+ CONVERT(VARCHAR(30), @cnt) + ','
SET @cnt=@cnt + 1
END
SET @sql=LEFT(@sql, Len(@sql) - 1)
SET @sql +=' FROM Split_cols '
--PRINT @sql
EXEC Sp_executesql @sql
答案 2 :(得分:0)
这将适用于任何未经编码的字符串和值
CREATE FUNCTION dbo.splitstring (@stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([ID] INT IDENTITY(1,1),[Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
-- USE THIS PARAMETER TO PASS VALUE
DECLARE @STRING VARCHAR(MAX)
DECLARE @COUNT INT
DECLARE @I INT
DECLARE @COLUMNNAME VARCHAR(MAX)
DECLARE @CREATETABLE VARCHAR(MAX)
DECLARE @INSERT VARCHAR(MAX)
IF OBJECT_ID('TEMPDB..##TEMPTABLE') IS NOT NULL
DROP TABLE ##TEMPTABLE
IF OBJECT_ID('TEMPDB..##RETURNLIST') IS NOT NULL
DROP TABLE ##RETURNLIST
SELECT * INTO ##RETURNLIST FROM dbo.splitstring(@STRING)
select @COUNT = COUNT(*) from ##RETURNLIST
SET @I=0
SET @CREATETABLE = 'CREATE TABLE ##TEMPTABLE ('
WHILE (@COUNT>0)
BEGIN
SET @COLUMNNAME = 'COLUMN'+ CONVERT(varchar(10), @I) + ' VARCHAR(MAX)'
SET @CREATETABLE = @CREATETABLE + @COLUMNNAME
IF(@COUNT<>1)
SET @CREATETABLE = @CREATETABLE + ', '
SET @I = @I+1
SET @COUNT = @COUNT -1;
END
SET @CREATETABLE = @CREATETABLE + ' )'
EXECUTE(@CREATETABLE)
SET @INSERT = 'INSERT INTO ##TEMPTABLE VALUES( '
WHILE (@I>0)
BEGIN
SET @INSERT = @INSERT +''''+ (SELECT NAME FROM ##RETURNLIST WHERE ID = @COUNT+1) +''''
IF(@I<>1)
SET @INSERT = @INSERT + ', '
SET @I = @I-1
SET @COUNT = @COUNT +1;
ENDenter code here
SET @INSERT = @INSERT + ' )'
EXECUTE(@INSERT)
EXECUTE('SELECT * FROM ##TEMPTABLE')
答案 3 :(得分:0)
您还没有给出每个列连接值的标准,所以我只是按降序加入它们。此解决方案可以处理列表中的任意数量的项目,但如果数字过高,您可能需要使用MAX RECURSION
查询提示。
DECLARE @strA NVARCHAR(MAX) = 'A1,A2,A3';
DECLARE @strB NVARCHAR(MAX) = 'B1,B2,B3,B4';
DECLARE @strC NVARCHAR(MAX) = 'C1,C2,C3';
WITH stringData AS (
--each group of comma separate values with a group identifier
SELECT 'a' AS grp, @strA AS strng
UNION ALL
SELECT 'b' AS grp, @strB
UNION ALL
SELECT 'c' AS grp, @strC
),
splitStrings AS (
--a recursive CTE to split the comma separated values
SELECT grp, CAST('' AS NVARCHAR(MAX)) AS item,
strng AS cText
FROM stringData
UNION ALL
SELECT grp,
CASE
WHEN CHARINDEX(N',',cText,0)>0 THEN LEFT(cText,CHARINDEX(N',',cText,0)-1) --SUBSTRING(cText,0,CHARINDEX(N',',cText,0))
ELSE cText
END,
RIGHT(cText,LEN(cText)-CHARINDEX(N',',cText,0))
FROM splitStrings
WHERE cText!=item
)
SELECT grp,
item,
ROW_NUMBER() OVER(PARTITION BY grp ORDER BY item) AS rnum
INTO #stringValues --put the results in a temp table so we don't need to execute the recursive CTE more than once
FROM splitStrings
WHERE len(item)>0;
DECLARE @maxNum INT = (SELECT MAX(rnum) FROM #stringValues);
--join the values together
WITH allNums AS (
SELECT 1 AS num
UNION ALL
SELECT num+1
FROM allNums
WHERE num<@maxNum
)
SELECT sa.item AS colA,
sb.item AS colB,
sc.item AS colC
FROM allNums
LEFT JOIN #stringValues AS sa ON sa.rnum=allNums.num AND sa.grp='A'
LEFT JOIN #stringValues AS sb ON sb.rnum=allNums.num AND sb.grp='B'
LEFT JOIN #stringValues AS sc ON sc.rnum=allNums.num AND sc.grp='C'
DROP TABLE #stringValues;