Split one field into multiple using a delimiter

  • I am trying to figure out how to split one single field that has data with commas into multiple fields. Ideally, this is something I would need to do in a stored procedure. I have an nvarchar(255). I tried using a combination of left, right and mid, but the positions aren't consistant.

  • You should look for split string functions on this site.

    There are numerous solutions available.

    One pretty fast solution is described at the end of the Tally Table article referenced in my signature.

    You also might look for a CLR solution, if you're familiar with CLR programming.



    Lutz
    A pessimist is an optimist with experience.

    How to get fast answers to your question[/url]
    How to post performance related questions[/url]
    Links for Tally Table [/url] , Cross Tabs [/url] and Dynamic Cross Tabs [/url], Delimited Split Function[/url]

  • Here is one way to solve the problem:

    declare @STR varchar(200)

    set @STR = 'Apple, Banana,Orange, Pinapple, Lemon'

    declare @result table (string varchar(100))

    declare @start int

    declare @end int

    set @start = 1

    set @end = charindex(',', @STR) - 1 -- Find first comma

    while @end > 0

    begin

    insert into @result

    select ltrim(substring(@str, @start, @end - @start + 1))

    set @start = @end + 2 -- We want to skip the comma, hence add to the position after

    set @end = charindex(',', @STR, @start + 1) - 1 -- Skip comma, subtract one to avoid it in the end

    end

    select *

    from @result

    /Markus

  • Hunterwood (3/2/2010)


    Here is one way to solve the problem:

    declare @STR varchar(200)

    set @STR = 'Apple, Banana,Orange, Pinapple, Lemon'

    declare @result table (string varchar(100))

    declare @start int

    declare @end int

    set @start = 1

    set @end = charindex(',', @STR) - 1 -- Find first comma

    while @end > 0

    begin

    insert into @result

    select ltrim(substring(@str, @start, @end - @start + 1))

    set @start = @end + 2 -- We want to skip the comma, hence add to the position after

    set @end = charindex(',', @STR, @start + 1) - 1 -- Skip comma, subtract one to avoid it in the end

    end

    select *

    from @result

    /Markus

    Well, Markus, that's one way to do it...

    But I think you should read the article I referred to in my prev. post, too...

    The WHILE loop approach performs almost as bad as (or even equivalent to) a cursor solution. There are much better solutions available. And easy to find on this side, too... 😉



    Lutz
    A pessimist is an optimist with experience.

    How to get fast answers to your question[/url]
    How to post performance related questions[/url]
    Links for Tally Table [/url] , Cross Tabs [/url] and Dynamic Cross Tabs [/url], Delimited Split Function[/url]

  • lmu92 (3/2/2010)


    You should look for split string functions on this site.

    There are numerous solutions available.

    One pretty fast solution is described at the end of the Tally Table article referenced in my signature.

    You also might look for a CLR solution, if you're familiar with CLR programming.

    Ok, since I am a total moron, can you dumb down the Tally Table for me? Is the number of records in a tally table equate to the number of records in the table I want to parse (40,000), or the number of fields I think I will need to parse out a single record (6)? Once I create the Tally Table, can I run this as a stored procedure in SQL 2005?

  • david.pelizzari (3/2/2010)


    lmu92 (3/2/2010)


    You should look for split string functions on this site.

    There are numerous solutions available.

    One pretty fast solution is described at the end of the Tally Table article referenced in my signature.

    You also might look for a CLR solution, if you're familiar with CLR programming.

    Ok, since I am a total moron, can you dumb down the Tally Table for me? Is the number of records in a tally table equate to the number of records in the table I want to parse (40,000), or the number of fields I think I will need to parse out a single record (6)? Once I create the Tally Table, can I run this as a stored procedure in SQL 2005?

    The Tally (or numbers) table contains of a column that includes consecutive numbers. You'd need as many numbers in there to match the longest character you want to split.

    I can't explain it better than Jeff did in the section "Going all the way... do the Split" in the article I referred to.



    Lutz
    A pessimist is an optimist with experience.

    How to get fast answers to your question[/url]
    How to post performance related questions[/url]
    Links for Tally Table [/url] , Cross Tabs [/url] and Dynamic Cross Tabs [/url], Delimited Split Function[/url]

  • david.pelizzari (3/2/2010)


    lmu92 (3/2/2010)


    You should look for split string functions on this site.

    There are numerous solutions available.

    One pretty fast solution is described at the end of the Tally Table article referenced in my signature.

    You also might look for a CLR solution, if you're familiar with CLR programming.

    Ok, since I am a total moron, can you dumb down the Tally Table for me? Is the number of records in a tally table equate to the number of records in the table I want to parse (40,000), or the number of fields I think I will need to parse out a single record (6)? Once I create the Tally Table, can I run this as a stored procedure in SQL 2005?

    The Tally table only needs the same number of rows as the maximum width +2 of the "field" you want to split. That's also covered in the article in the section where I explain why I made my Tally table 11,000 rows long.

    Like Lutz said, anything more that I say here would be a regurgitation of the article. Go through the examples in article... the light will come on.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Imu, I didn't see your post until after I posted my solution..

    From now on, I will look for a Tally-solution first, before trying with a loop (or cursor)... 😉

    /Markus

  • it may one of solution:

    DECLARE @data NVARCHAR(MAX),

    @delimiter NVARCHAR(5)

    SELECT @data = '1,2,3,6,7,8,R,a,n,g,a,n,a,t,h',@delimiter = ','

    DECLARE @textXML XML;

    SELECT @textXML = CAST('<d>' + REPLACE(@data, @delimiter, '</d><d>') + '</d>' AS XML);

    SELECT @textXML

    SELECT T.split.value('.', 'nvarchar(max)') AS data

    FROM @textXML.nodes('/d') T (split)

  • Mohamed Asane (3/3/2010)


    it may one of solution:

    DECLARE @data NVARCHAR(MAX),

    @delimiter NVARCHAR(5)

    SELECT @data = '1,2,3,6,7,8,R,a,n,g,a,n,a,t,h',@delimiter = ','

    DECLARE @textXML XML;

    SELECT @textXML = CAST('<d>' + REPLACE(@data, @delimiter, '</d><d>') + '</d>' AS XML);

    SELECT @textXML

    SELECT T.split.value('.', 'nvarchar(max)') AS data

    FROM @textXML.nodes('/d') T (split)

    I agree... it's a solution that works. Try it on a couple of hundred thousand rows and see if you like the performance, though.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Hunterwood (3/2/2010)


    Here is one way to solve the problem:

    declare @STR varchar(200)

    set @STR = 'Apple, Banana,Orange, Pinapple, Lemon'

    declare @result table (string varchar(100))

    declare @start int

    declare @end int

    set @start = 1

    set @end = charindex(',', @STR) - 1 -- Find first comma

    while @end > 0

    begin

    insert into @result

    select ltrim(substring(@str, @start, @end - @start + 1))

    set @start = @end + 2 -- We want to skip the comma, hence add to the position after

    set @end = charindex(',', @STR, @start + 1) - 1 -- Skip comma, subtract one to avoid it in the end

    end

    select *

    from @result

    /Markus

    THis one will work better as above will skip the last word ( here "lemon")

    SET STATISTICS IO ON

    declare @STR varchar(200)

    set @STR = 'Apple, Banana,Orange, Pinapple, Lemon'

    set @STR = @STR + ','

    declare @result table (string varchar(100))

    declare @start int

    declare @end int

    set @start = 1

    set @end = charindex(',', @STR) - 1 -- Find first comma

    while @end > 0

    begin

    insert into @result

    select ltrim(substring(@str, @start, @end - @start + 1))

    set @start = @end + 2 -- We want to skip the comma, hence add to the position after

    set @end = charindex(',', @STR, @start + 1) - 1 -- Skip comma, subtract one to avoid it in the end

    end

    select *

    from @result

    -------Bhuvnesh----------
    I work only to learn Sql Server...though my company pays me for getting their stuff done;-)

  • Heh... you really really don't won't to use even well written While Loops for this though.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • david.pelizzari (3/2/2010)


    I am trying to figure out how to split one single field that has data with commas into multiple fields. Ideally, this is something I would need to do in a stored procedure. I have an nvarchar(255). I tried using a combination of left, right and mid, but the positions aren't consistant.

    Code: http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx

    Performance Results: http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html

    Paul

  • It would have been helpful if you had posted some data

    but does this sort of approach help you out?

    IF NOT OBJECT_ID('tempdb.dbo.#FOO', 'U') IS NULL

    DROP TABLE #FOO

    SELECT 'Apple,Banana,Orange,Pineapple,Lemon,pear' AS BulkColumn

    INTO #FOO

    UNION ALL SELECT '1,2,3,4,5,6'

    UNION ALL SELECT 'dave,harry,john,peter,fred, bill'

    ;

    WITH cteTally

    AS

    (

    SELECT TOP 20000 ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS pk

    FROM master.sys.All_Columns t1

    CROSS JOIN master.sys.All_Columns t2

    )

    SELECT * FROM #FOO

    CROSS APPLY

    (

    SELECT

    [1] AS COL1,

    [2] AS COL2,

    [3] AS COL3,

    [4] AS COL4,

    [5] AS COL5,

    [6] AS COL6

    FROM

    (

    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ROW,

    NULLIF(SUBSTRING(BulkColumn+',', pk, CHARINDEX(',', BulkColumn+',', pk)-pk), '') AS Value

    FROM cteTally

    WHERE pk-1<LEN(BulkColumn)+LEN(',') AND SUBSTRING(',' + BulkColumn + ',', pk, 1)=','

    ) AS Z

    PIVOT

    (

    MAX(Value) for ROW in

    (

    [1],

    [2],

    [3],

    [4],

    [5],

    [6]

    )

    )

    AS pvt

    )

    AS Y

  • This is what we actually came up with after all the great help on here to fuel the brain:

    Update [ad import]

    Set ADBU =

    replace (substring([distinguished name],

    patindex('%Workstations,OU=%', [distinguished name] )+

    charindex(',', substring([distinguished name],patindex('%Workstations,OU=%', [distinguished name] )+17,30),2 )

    +17+3,4),',','')

    where [distinguished name] like '%Workstations,OU=%'

Viewing 15 posts - 1 through 15 (of 16 total)

You must be logged in to reply to this topic. Login to reply