Last number from a Text Field

  • Hey guys, been struggling with this one for a bit and about to head home, but does anyone know how I'd get "18669911.96" out of this Text field?

    "FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96"

    It will always be the last value in the Field but couldn't use Right() not knowing if a trade would be $1 or $1,000,000,000, can't use CHARINDEX() - having excluded the first 20 or 30 characters to avoid the first mention of the Currency Codes - because there are plenty of options and the other numbers mean I can't just grab the numbers out of the Text field.

    I see the solution as being to take everything to the right of the right-most space (having put it through RTRIM just to be safe), but can't find any examples of this to use.

    Thanks,

    Nathan

  • Pls try the following Query. It is Coming Correctly. I m not 100% Sure.. i m not checked for all cases.

    Select reverse(Substring(Reverse('FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96'),

    0,

    Patindex('% %', reverse('FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96'))))

  • See if this helps.

    ; WITH TestCTE

    AS

    (

    SELECT'FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96' AS SomeText

    UNION ALL

    SELECT'FFX Buy $/Sell $, Broker 471 MATURITY 11/05/09 SOLD $878.96' AS SomeText

    UNION ALL

    SELECT'FFX Buy $/Sell $, Broker 471 MATURITY 11/05/09 SOLD $48' AS SomeText

    )

    SELECTSomeText, RIGHT( RTRIM( SomeText ), CHARINDEX( ' ', REVERSE( RTRIM( SomeText ) ) + ' ' ) - 1 )

    FROMTestCTE

    --Ramesh


  • This will work 100%....

    Declare @STR Varchar(100)

    Set @STR = 'Ssfsdfsdf dgdgg,.:as123'

    Select reverse(Substring(Reverse(@Str),

    0,

    Patindex('%[^0-9]%', reverse(@Str))))

    Kindly Reply me weather it's working or not...

  • siva_pdm40 (5/29/2009)


    This will work 100%....

    Kindly Reply me weather it's working or not...

    Hi Siva,

    your statement runs fine in only with round number,

    try this

    declare @abc varchar(50)

    set @abc = 'THE GOOD DAY IS TODAY 100,00.00'

    select @abc = replace(@ABC,' ','')

    select @abc = rtrim(@ABC)

    select right(@ABC,PATINDEX(('%[A-Z]%'),reverse(@ABC))-1)

    RESULT

    100,00.00

    --Yours Select reverse(Substring(Reverse(@ABC),0,Patindex('%[^0-9]%', reverse(@ABC))))

    RESULT

    00

    ARUN SAS

  • Ramesh (5/29/2009)


    See if this helps.

    ; WITH TestCTE

    AS

    (

    SELECT'FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96' AS SomeText

    UNION ALL

    SELECT'FFX Buy $/Sell $, Broker 471 MATURITY 11/05/09 SOLD $878.96' AS SomeText

    UNION ALL

    SELECT'FFX Buy $/Sell $, Broker 471 MATURITY 11/05/09 SOLD $48' AS SomeText

    )

    SELECTSomeText, RIGHT( RTRIM( SomeText ), CHARINDEX( ' ', REVERSE( RTRIM( SomeText ) ) + ' ' ) - 1 )

    FROMTestCTE

    Spot on, Ramesh. And, you made it easy to convert to the MONEY datatype so you can use the result number for calculations.

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

  • Spot on, Ramesh. And, you made it easy to convert to the MONEY datatype so you can use the result number for calculations.

    Hi jeff,

    Ok with the Ramesh statements,

    But, for the text like “THE GOOD DAY IS TODAY$100,00.00'”

    (i.e. without the space)

    Remesh Result

    --TODAY$100,00.00

    But using this

    declare @abc varchar(50)

    set @abc = 'THE GOOD DAY IS TODAY$100,00.00'

    select right(@ABC,PATINDEX(('%[A-Z]%'),reverse(@ABC))-1)

    give us the correct

    Result

    --$100,00.00

    Which one is better in all Situations?

    ARUN SAS

  • Jeff Moden (5/29/2009)


    Spot on, Ramesh. And, you made it easy to convert to the MONEY datatype so you can use the result number for calculations.

    Thanks Jeff:-), it just that one of the things that I learned from SSC.

    --Ramesh


  • arun.sas (5/29/2009)


    Which one is better in all Situations?

    ARUN SAS

    If you read the OP's original post he has mentioned that he wanted the entire text that follows the last space.

    Though your solution can be modified to meet the OP's requirements but it probably would be slower on larger resultsets because of the pattern search. Am I correct, Jeff?

    --Ramesh


  • arun.sas (5/29/2009)


    Which one is better in all Situations?

    ARUN SAS

    If you read the OP's original post he has mentioned that he wanted the entire text that follows the last space.

    Though your solution can be modified to meet the OP's requirements but it probably would be slower on larger resultsets because of the pattern search. Am I correct, Jeff?

    --Ramesh


  • arun.sas (5/29/2009)


    Spot on, Ramesh. And, you made it easy to convert to the MONEY datatype so you can use the result number for calculations.

    Hi jeff,

    Ok with the Ramesh statements,

    But, for the text like “THE GOOD DAY IS TODAY$100,00.00'”

    (i.e. without the space)

    Remesh Result

    --TODAY$100,00.00

    But using this

    declare @abc varchar(50)

    set @abc = 'THE GOOD DAY IS TODAY$100,00.00'

    select right(@ABC,PATINDEX(('%[A-Z]%'),reverse(@ABC))-1)

    give us the correct

    Result

    --$100,00.00

    Which one is better in [font="Arial Black"]all[/font] Situations?

    ARUN SAS

    Heh... no food fights, folks. 😛

    Actually... neither "is better in all situations". Ramesh's very nicely solves the original problem of finding the operand to the right of the last embedded space in the string. Your's very nicely finds the operand to the right of the last embedded letter in the string and leaves a leading space if one is present (which, of course, is easily fixed).

    What if you have something like any of the following?

    DECLARE @abc VARCHAR(50)

    SELECT @abc = 'Today is day 1#$100,00.00 '

    SELECT RIGHT(@ABC,PATINDEX(('%[A-Z]%'),REVERSE(@ABC))-1)

    SELECT RIGHT( RTRIM( @abc ), CHARINDEX( ' ', REVERSE( RTRIM( @abc ) ) + ' ' ) - 1 )

    Both methods will fail if the problem definition is to get the right most numeric value (if there is one) along with a "$" if present because both will return too much... both will return the "1#".

    The following method isn't perfect for "all situations" either, but it handles more than either of the two methods above.

    DECLARE @abc VARCHAR(50)

    SELECT @abc = 'Today is day 1#$100,00.00 '

    SELECT RIGHT(d.ABC,PATINDEX(('%[^-+0-9,.$]%'),REVERSE(d.ABC))-1)

    FROM (SELECT RTRIM(@ABC) AS ABC) d

    But, even that won't withstand something like the following...

    DECLARE @abc VARCHAR(50)

    SELECT @abc = 'Today is day 1$100,00.00 '

    SELECT RIGHT(d.ABC,PATINDEX(('%[^-+0-9,.$]%'),REVERSE(d.ABC))-1)

    FROM (SELECT RTRIM(@ABC) AS ABC) d

    Of course, the example data line the OP gave had no "$" sign in it, so technically, the following would be correct...

    DECLARE @abc VARCHAR(50)

    SELECT @abc = 'Today is day 1$100,00.00 '

    SELECT RIGHT(d.ABC,PATINDEX(('%[^-+0-9,.]%'),REVERSE(d.ABC))-1)

    FROM (SELECT RTRIM(@ABC) AS ABC) d

    So, what is best to meet "all situations"? None of the above because, in theory, you could also have the following... 😛

    DECLARE @abc VARCHAR(50)

    SELECT @abc = 'Today is day 1$,,,100,00.00 '

    SELECT RIGHT(d.ABC,PATINDEX(('%[^-+0-9,.]%'),REVERSE(d.ABC))-1)

    FROM (SELECT RTRIM(@ABC) AS ABC) d

    Ramesh's code did meet the requirements for the precise stated problem, though.

    Personally, I'd hunt down and feed some very high velocity pork chops to the person who provided data in such an ill conceived manner to begin with. 😉

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

  • Ramesh (5/30/2009)


    arun.sas (5/29/2009)


    Which one is better in all Situations?

    ARUN SAS

    If you read the OP's original post he has mentioned that he wanted the entire text that follows the last space.

    Though your solution can be modified to meet the OP's requirements but it probably would be slower on larger resultsets because of the pattern search. Am I correct, Jeff?

    Good question... I've never actually tested it. My inclination would be to say that CHARINDEX will be slightly faster than PATINDEX. But you know I don't speculate. Let's test and find out because "A Developer must not guess... a Developer must KNOW." 😉

    Here's a million row test table that creates a 32 character column of letters and digits all mixed up...

    DROP TABLE JBMTest

    GO

    --===== Create and populate a 1,000,000 row test table.

    SELECT TOP 1000000

    SomeID = IDENTITY(INT,1,1),

    SomeHex = CAST(REPLACE(NEWID(),'-','') AS CHAR(32))

    INTO dbo.JBMTest

    FROM Master.dbo.SysColumns t1,

    Master.dbo.SysColumns t2 --Lack of join criteria makes this a CROSS-JOIN

    --===== A table is not properly formed unless a clustered index has been assigned

    -- Takes about 1 second to execute.

    ALTER TABLE dbo.JBMTest

    ADD PRIMARY KEY CLUSTERED (SomeID)

    And here's a comparison between CHARINDEX and PATINDEX. Notice how the results are thrown away using the @Bitbucket variable to keep the display out of the picture...

    --===== Supress the auto-display of rowcounts

    SET NOCOUNT ON

    --===== Create a place to throw things away

    DECLARE @Bitbucket INT

    --===== Turn on the timers and test the two functions

    -- throwing away the results to keep the measurement

    -- as pure as possible.

    SET STATISTICS TIME ON

    --===== Test for two given characters (CHARINDEX)

    SELECT @Bitbucket = CHARINDEX('0d',SomeHex)

    FROM dbo.JBMTest

    --===== Test for two given characters (PATINDEX)

    SELECT @Bitbucket = PATINDEX('%0d%',SomeHex)

    FROM dbo.JBMTest

    --===== Test for one given character (CHARINDEX)

    SELECT @Bitbucket = CHARINDEX('d',SomeHex)

    FROM dbo.JBMTest

    --===== Test for one given character (PATINDEX)

    SELECT @Bitbucket = PATINDEX('%d%',SomeHex)

    FROM dbo.JBMTest

    --===== Test for one given character as a range (PATINDEX)

    SELECT @Bitbucket = PATINDEX('%[d-d]%',SomeHex)

    FROM dbo.JBMTest

    SET STATISTICS TIME OFF

    That yields the following on by humble desktop box...

    [font="Courier New"]

    SQL Server Execution Times:

    CPU time = 0 ms, elapsed time = 0 ms.

    SQL Server Execution Times:

    CPU time = 1813 ms, elapsed time = 1826 ms.

    SQL Server Execution Times:

    CPU time = 2234 ms, elapsed time = 2239 ms.

    SQL Server Execution Times:

    CPU time = 1312 ms, elapsed time = 1312 ms.

    SQL Server Execution Times:

    CPU time = 1416 ms, elapsed time = 1416 ms.

    SQL Server Execution Times:

    CPU time = 2312 ms, elapsed time = 2312 ms.

    [/font]

    Now I can say that CHARINDEX is faster than PATINDEX especially if you're looking for just one character. But, over a million rows, it's still a pretty close race and PATINDEX may bring in some additional functionality like it did in some of the examples I presented in my previous post for this problem.

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

  • NathanB (5/29/2009)


    Hey guys, been struggling with this one for a bit and about to head home, but does anyone know how I'd get "18669911.96" out of this Text field?

    "FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96"

    It will always be the last value in the Field but couldn't use Right() ...

    using a delimiting table valued function the solution is straightforward. My fListToVarchars() (link to related topic with source) would return a table of ( item, itemSequence ).

    select ST.fieldOfInterest, reverse(X.item) as lastItem

    from SomeTable as ST

    cross apply global.dbo.fListToVarchars( reverse( ST.fieldOfInterest ), ' ' ) as X

    where X.itemSequence = 1

  • Hey Jeff, I really appreciate you for taking time in detailing the solutions, listing out the issues with them & testing them.

    BTW, I am ducking down:hehe:, in case the high velocity pork chops are hitting in my way:-D

    --Ramesh


  • antonio.collins (5/30/2009)


    NathanB (5/29/2009)


    Hey guys, been struggling with this one for a bit and about to head home, but does anyone know how I'd get "18669911.96" out of this Text field?

    "FFX Buy USD/Sell AUD, Broker 703 MATURITY 11/05/09 SOLD AUD 18,669,911.96"

    It will always be the last value in the Field but couldn't use Right() ...

    using a delimiting table valued function the solution is straightforward. My fListToVarchars() (link to related topic with source) would return a table of ( item, itemSequence ).

    select ST.fieldOfInterest, reverse(X.item) as lastItem

    from SomeTable as ST

    cross apply global.dbo.fListToVarchars( reverse( ST.fieldOfInterest ), ' ' ) as X

    where X.itemSequence = 1

    There's a very steep penalty in performance in all of that, though. XML splitters are quite a bit slower than Tally table splitters and the overhead of calling a function on something like this is a real killer. Of course... here's the test that shows that...

    First, the test code with to generate just 10,000 rows of data...

    --===== Create and populate a test table.

    SELECT TOP 10000 --<<<==== Change this number to vary the rows in the test

    SomeID = IDENTITY(INT,1,1),

    SomeString = CAST(REPLACE(NEWID(),'-',' ') AS CHAR(32)) + ' '

    + CONVERT(VARCHAR(20),CAST(CHECKSUM(NEWID())/100.0 AS MONEY),1)

    INTO dbo.JBMTest

    FROM Master.dbo.SysColumns t1

    CROSS JOIN

    Master.dbo.SysColumns t2

    --===== A table is not properly formed unless a clustered index has been assigned

    -- Takes about 1 second to execute.

    ALTER TABLE dbo.JBMTest

    ADD PRIMARY KEY CLUSTERED (SomeID)

    Here's the performance test between your function and Ramesh's...

    --===== Supress the auto-display of rowcounts

    SET NOCOUNT ON

    --===== Create a place to throw things away

    DECLARE @Bitbucket VARCHAR(50)

    --

    --===== Antonio's Function =====

    PRINT REPLICATE('=',78)

    PRINT '--===== Antonio''s Function ====='

    SET STATISTICS TIME ON

    select @Bitbucket = Reverse(X.item)

    from dbo.JBMTest as ST

    cross apply dbo.fListToVarchars( reverse( ST.SomeString ), ' ' ) as X

    where X.itemSequence = 1

    SET STATISTICS TIME OFF

    --

    --===== Ramesh''s Inline Code =====

    PRINT REPLICATE('=',78)

    PRINT '--===== Ramesh''s Inline Code ====='

    SET STATISTICS TIME ON

    SELECT @Bitbucket = RIGHT( RTRIM( SomeString ), CHARINDEX( ' ', REVERSE( RTRIM( SomeString ) ) + ' ' ) - 1 )

    FROM dbo.JBMTest

    SET STATISTICS TIME OFF

    And, here's the results...

    [font="Courier New"]==============================================================================

    --===== Antonio's Function =====

    SQL Server Execution Times:

    CPU time = 22156 ms, elapsed time = 25535 ms.

    ==============================================================================

    --===== Ramesh's Inline Code =====

    SQL Server Execution Times:

    CPU time = 31 ms, elapsed time = 36 ms.

    [/font]

    Keep in mind that was 22 seconds to process just 10,000 rows. Generic functions that can solve "ALL" problems normally become a problem themselves. Unless they have proven performance characteristics, I generally steer away from such functions in favor of inline functionality. And, if you take a look, the inline functionality has less complicated code in this instance, as well.

    --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 15 posts - 1 through 15 (of 27 total)

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