Split multiple string's into multiple columns

后端 未结 4 1379
深忆病人
深忆病人 2020-12-22 13:55

I have the following three different strings which needs to split into three different columns.

Example:

String 1:

Declare @         


        
相关标签:
4条回答
  • 2020-12-22 14:07

    I know its a bit heavy but it will work

    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
    
    0 讨论(0)
  • 2020-12-22 14:07

    You haven't given any criteria for joining the values together for each of the rows of columns so I've just joined them in descending order. This solution can handle any number of items in the lists but if the number gets too high you may need to use the MAX RECURSION query hint.

    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;
    
    0 讨论(0)
  • 2020-12-22 14:14

    THIS WILL WORK WITH ANY NUMBER OF STRINGS AND VALUES NOT HARDCODED

    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')
    
    0 讨论(0)
  • 2020-12-22 14:19

    If you have atmost three values then try this.

    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
    

    Or

    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 
    
    0 讨论(0)
提交回复
热议问题