将多个字符串拆分为多列

Posted

技术标签:

【中文标题】将多个字符串拆分为多列【英文标题】:Split multiple string's into multiple columns 【发布时间】:2014-12-03 06:22:17 【问题描述】:

我有以下三个不同的字符串需要分成三个不同的列。

示例

字符串 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

尝试:

SQL 小提琴:http://sqlfiddle.com/#!3/d41d8/41345

【问题讨论】:

之前询问了无数次。请尝试搜索.... @MitchWheat OP 询问了如何拆分并将其转换为列 你的意思是这样的:***.com/questions/27250433/… 【参考方案1】:

我知道它有点重,但它会起作用

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

【讨论】:

【参考方案2】:

如果你最多有三个值,那么试试这个。

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 

【讨论】:

我想将结果插入到#temp 表中。并且字符串的值是动态的。 @MAK - 只需在末尾添加INTO #TEMP 好的!但正如我所说,价值观是动态的。我怎么会在这里手动知道每个值的索引值。 我们可以用同样的方法吗:***.com/questions/27255512/string-into-single-column for MULTIPLE STRINGS @MAK 不,你想将 CSV 转换为多行,但这里应该是多列。【参考方案3】:

这将适用于任意数量的非硬编码字符串和值

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')

【讨论】:

【参考方案4】:

您没有给出将每行列的值连接在一起的任何标准,所以我只是按降序连接它们。此解决方案可以处理列表中任意数量的项目,但如果数量过多,您可能需要使用 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;

【讨论】:

以上是关于将多个字符串拆分为多列的主要内容,如果未能解决你的问题,请参考以下文章

在 PowerShell 中将字符串拆分为多列

R语言将dataframe的某个字符串列拆分为多列实战

将 Spark Dataframe 字符串列拆分为多列

将 Spark Dataframe 字符串列拆分为多列

Pandas使用str属性获取数据列的字符串方法类split函数基于指定分隔符拆分数据列的内容为列表设置参数n控制拆分的次数设置expand参数将拆分结果列表内容转化为多列dataframe

Pandas使用split函数基于指定分隔符拆分数据列的内容为列表设置expand参数将拆分结果列表内容转化为多列数据并添加到原数据中replace函数基于正则表达式替换字符串数据列中的匹配内容