Parse the string value

  • Hi all,

    Could you please help me to parse string? The format of the string below:

    Data:A:B:C:20:0:0

    I need to fetch number 20 from this string. So,

    1. it should always start with Data

    2. It should be always after fourth colon

    3. The length of this can be different. That is, it can be 20 or 20.05. Can this be limited to the fifth colon?

    Thanks

  • One method would be to use DelimitedSplit8K_LEAD , which returns the ordinal position of the string, and then you can easily get the Nth value:

    SELECT *
    FROM Utility.dbo.DelimitedSplit8K_LEAD('Data:A:B:C:20:0:0',':')
    WHERE ItemNumber = 5;

    If you were on Azure SQL Database, you could also use STRING_SPLIT and include the optional ordinal parameter:

    SELECT *
    FROM STRING_SPLIT('Data:A:B:C:20:0:0',':',1)
    WHERE ordinal = 5;

    Hopefully this parameter will be added to SQL Server 2022 as well.

    If, for some reason, you're against functions, you could take the definition DelimitedSplit8k_LEAD and inline it into your query. Otherwise you could nest some CHARINDEX functions, but it's... Well, pretty ugly.

    SELECT SUBSTRING(V.YourString,CI4.CI+1, CI5.CI - CI4.CI - 1)
    FROM (VALUES('Data:A:B:C:20:0:0'))V(YourString)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString)))CI1(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI1.CI+1)))CI2(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI2.CI+1)))CI3(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI3.CI+1)))CI4(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI4.CI+1)))CI5(CI);

    This solution also assumes that there is always another delimiter after the value you want.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Thom A wrote:

    ...

    SELECT SUBSTRING(V.YourString,CI4.CI+1, CI5.CI - CI4.CI - 1)
    FROM (VALUES('Data:A:B:C:20:0:0'))V(YourString)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString)))CI1(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI1.CI+1)))CI2(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI2.CI+1)))CI3(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI3.CI+1)))CI4(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI4.CI+1)))CI5(CI);

    This solution also assumes that there is always another delimiter after the value you want.

    It's easy enough to eliminate that particular worry by adding a trailing delim yourself, just to make sure there is one:

    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString+':',CI4.CI+1)))CI5(CI);

     

    SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".

  • Just a quick question, what are the variations of the values in the first four columns?

    😎

     

  • ScottPletcher wrote:

    Thom A wrote:

    ...

    SELECT SUBSTRING(V.YourString,CI4.CI+1, CI5.CI - CI4.CI - 1)
    FROM (VALUES('Data:A:B:C:20:0:0'))V(YourString)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString)))CI1(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI1.CI+1)))CI2(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI2.CI+1)))CI3(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI3.CI+1)))CI4(CI)
    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString,CI4.CI+1)))CI5(CI);

    This solution also assumes that there is always another delimiter after the value you want.

    It's easy enough to eliminate that particular worry by adding a trailing delim yourself, just to make sure there is one:

    CROSS APPLY (VALUES(CHARINDEX(':',V.YourString+':',CI4.CI+1)))CI5(CI);

    Rather - I would do that in the first VALUES statement:

    FROM (VALUES(concat('Data:A:B:C:20:0:0', replicate(':', 6))))    V(YourString)

    And I would make sure there is always the max number + 1 - that way a string that has 0 delimiters will still be parsed correctly.  This also allows you to parse out the last element using that last delimiter instead of using some arbitrary end length for the substring or the total length of the string.

     

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • Multiple CROSS APPLYs do add a tiny bit of overhead and, in this case, a fair bit of complexity.  We can simplify Thom's good code a bit by cascading the CHARINDEX() function in a single VALUES()  Table Valued Constructor (AKA Derived Table).

    Also, I assume that you actually want to do this to a column in the table.  In the following, change "Your Table" to the name of your table and "SomeString" with the name of the column you're trying to do all this with.

     SELECT D5 = SUBSTRING(SomeString,ca.P4,CHARINDEX(':',SomeString,ca.P4)-ca.P4)
    FROM dbo.YourTable
    CROSS APPLY (VALUES
    (
    CHARINDEX(':',SomeString+':'
    ,CHARINDEX(':',SomeString
    ,CHARINDEX(':',SomeString
    ,CHARINDEX(':',SomeString)+1)+1)+1)+1
    )
    )ca(P4)
    ;

     

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

  • Hi Thom,

    Unfortunately, I have too old version - SQL Server 2008 🙂

  • christi1711 wrote:

    Hi Thom,

    Unfortunately, I have too old version - SQL Server 2008 🙂

    Why did you post in the SQL Server 2016 forum then? 2008 has been completely unsupported since mid 2020; you really should have upgraded by now or at least finished planning your upgrade path and be about to be deploying it.

    If you're using completely unsupported software, then the CHARINDEX method will still work, or you could use DelimitedSplit8k instead (which DelimitedSplit8k_LEAD is based on), and is linked to in the article.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • My bad.

    Sorry.

    P.S. @jeff Moden your method with cross apply works!

    Thank you

  • christi1711 wrote:

    My bad. Sorry.

    P.S. @jeff Moden your method with cross apply works! Thank you

    Thank you for the feedback, Christi.

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

Viewing 10 posts - 1 through 9 (of 9 total)

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