How to split a comma-separated value to columns

后端 未结 30 3955
刺人心
刺人心 2020-11-21 04:38

I have a table like this

Value   String
-------------------
1       Cleo, Smith

I want to separate the comma delimited string into two colu

相关标签:
30条回答
  • 2020-11-21 04:53

    question is simple, but problem is hot :)

    So I create some wrapper for string_split() which pivot result in more generic way. It's table function which returns values (nn, value1, value2, ... , value50) - enough for most CSV lines. If there are more values, they will wrap to next line - nn indicate line number. Set third parameter @columnCnt = [yourNumber] to wrap at specific position:

    alter FUNCTION fn_Split50
    (   
        @str varchar(max),
        @delim char(1), 
        @columnCnt int = 50
    )
    RETURNS TABLE 
    AS
    RETURN 
    (
        SELECT * 
        FROM (SELECT 
                nn = (nn - 1) / @columnCnt + 1, 
                nnn = 'value' + cast(((nn - 1) % @columnCnt) + 1 as varchar(10)), 
                value
            FROM (SELECT 
                nn = ROW_NUMBER() over (order by (select null)),
                value
                FROM string_split(@str, @delim) aa
                ) aa
            where nn > 0
        ) bb
        PIVOT  
        (  
        max(value) 
        FOR nnn IN (    
            value1, value2, value3, value4, value5, value6, value7, value8, value9, value10,
            value11, value12, value13, value14, value15, value16, value17, value18, value19, value20,
            value21, value22, value23, value24, value25, value26, value27, value28, value29, value30,
            value31, value32, value33, value34, value35, value36, value37, value38, value39, value40,
            value41, value42, value43, value44, value45, value46, value47, value48, value49, value50        
         )  
        ) AS PivotTable 
    )
    

    Example of using:

    select * from dbo.fn_split50('zz1,aa2,ss3,dd4,ff5', ',', DEFAULT)
    

    select * from dbo.fn_split50('zz1,aa2,ss3,dd4,ff5,gg6,hh7,jj8,ww9,qq10', ',', 3)
    

    select * from dbo.fn_split50('zz1,11,aa2,22,ss3,33,dd4,44,ff5,55,gg6,66,hh7,77,jj8,88,ww9,99,qq10,1010', ',',2)
    

    Hope, it will helps :)

    0 讨论(0)
  • 2020-11-21 04:54

    Try this (change instances of ' ' to ',' or whatever delimiter you want to use)

    CREATE FUNCTION dbo.Wordparser
    (
      @multiwordstring VARCHAR(255),
      @wordnumber      NUMERIC
    )
    returns VARCHAR(255)
    AS
      BEGIN
          DECLARE @remainingstring VARCHAR(255)
          SET @remainingstring=@multiwordstring
    
          DECLARE @numberofwords NUMERIC
          SET @numberofwords=(LEN(@remainingstring) - LEN(REPLACE(@remainingstring, ' ', '')) + 1)
    
          DECLARE @word VARCHAR(50)
          DECLARE @parsedwords TABLE
          (
             line NUMERIC IDENTITY(1, 1),
             word VARCHAR(255)
          )
    
          WHILE @numberofwords > 1
            BEGIN
                SET @word=LEFT(@remainingstring, CHARINDEX(' ', @remainingstring) - 1)
    
                INSERT INTO @parsedwords(word)
                SELECT @word
    
                SET @remainingstring= REPLACE(@remainingstring, Concat(@word, ' '), '')
                SET @numberofwords=(LEN(@remainingstring) - LEN(REPLACE(@remainingstring, ' ', '')) + 1)
    
                IF @numberofwords = 1
                  BREAK
    
                ELSE
                  CONTINUE
            END
    
          IF @numberofwords = 1
            SELECT @word = @remainingstring
          INSERT INTO @parsedwords(word)
          SELECT @word
    
          RETURN
            (SELECT word
             FROM   @parsedwords
             WHERE  line = @wordnumber)
    
      END
    

    Example usage:

    SELECT dbo.Wordparser(COLUMN, 1),
           dbo.Wordparser(COLUMN, 2),
           dbo.Wordparser(COLUMN, 3)
    FROM   TABLE
    
    0 讨论(0)
  • 2020-11-21 04:55

    This function is most fast:

    CREATE FUNCTION dbo.F_ExtractSubString
    (
      @String VARCHAR(MAX),
      @NroSubString INT,
      @Separator VARCHAR(5)
    )
    RETURNS VARCHAR(MAX) AS
    BEGIN
        DECLARE @St INT = 0, @End INT = 0, @Ret VARCHAR(MAX)
        SET @String = @String + @Separator
        WHILE CHARINDEX(@Separator, @String, @End + 1) > 0 AND @NroSubString > 0
        BEGIN
            SET @St = @End + 1
            SET @End = CHARINDEX(@Separator, @String, @End + 1)
            SET @NroSubString = @NroSubString - 1
        END
        IF @NroSubString > 0
            SET @Ret = ''
        ELSE
            SET @Ret = SUBSTRING(@String, @St, @End - @St)
        RETURN @Ret
    END
    GO
    

    Example usage:

    SELECT dbo.F_ExtractSubString(COLUMN, 1, ', '),
           dbo.F_ExtractSubString(COLUMN, 2, ', '),
           dbo.F_ExtractSubString(COLUMN, 3, ', ')
    FROM   TABLE
    
    0 讨论(0)
  • 2020-11-21 04:55

    it is so easy, you can take it by below query:

    DECLARE @str NVARCHAR(MAX)='ControlID_05436b78-04ba-9667-fa01-9ff8c1b7c235,3'
    SELECT LEFT(@str, CHARINDEX(',',@str)-1),RIGHT(@str,LEN(@str)-(CHARINDEX(',',@str)))
    
    0 讨论(0)
  • 2020-11-21 04:56

    Your purpose can be solved using following query -

    Select Value  , Substring(FullName, 1,Charindex(',', FullName)-1) as Name,
    Substring(FullName, Charindex(',', FullName)+1, LEN(FullName)) as  Surname
    from Table1
    

    There is no readymade Split function in sql server, so we need to create user defined function.

    CREATE FUNCTION Split (
          @InputString                  VARCHAR(8000),
          @Delimiter                    VARCHAR(50)
    )
    
    RETURNS @Items TABLE (
          Item                          VARCHAR(8000)
    )
    
    AS
    BEGIN
          IF @Delimiter = ' '
          BEGIN
                SET @Delimiter = ','
                SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
          END
    
          IF (@Delimiter IS NULL OR @Delimiter = '')
                SET @Delimiter = ','
    
    --INSERT INTO @Items VALUES (@Delimiter) -- Diagnostic
    --INSERT INTO @Items VALUES (@InputString) -- Diagnostic
    
          DECLARE @Item           VARCHAR(8000)
          DECLARE @ItemList       VARCHAR(8000)
          DECLARE @DelimIndex     INT
    
          SET @ItemList = @InputString
          SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
          WHILE (@DelimIndex != 0)
          BEGIN
                SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
                INSERT INTO @Items VALUES (@Item)
    
                -- Set @ItemList = @ItemList minus one less item
                SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
                SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
          END -- End WHILE
    
          IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
          BEGIN
                SET @Item = @ItemList
                INSERT INTO @Items VALUES (@Item)
          END
    
          -- No delimiters were encountered in @InputString, so just return @InputString
          ELSE INSERT INTO @Items VALUES (@InputString)
    
          RETURN
    
    END -- End Function
    GO
    
    ---- Set Permissions
    --GRANT SELECT ON Split TO UserRole1
    --GRANT SELECT ON Split TO UserRole2
    --GO
    
    0 讨论(0)
  • 2020-11-21 04:56

    With SQL Server 2016 we can use string_split to accomplish this:

    create table commasep (
     id int identity(1,1)
     ,string nvarchar(100) )
    
    insert into commasep (string) values ('John, Adam'), ('test1,test2,test3')
    
    select id, [value] as String from commasep 
     cross apply string_split(string,',')
    
    0 讨论(0)
提交回复
热议问题