8

I have a table with a nvarchar column. This column has values for example:

  • 983
  • 294
  • a343
  • a3546f

and so on.

I would like to take MAX of this values, but not as text but like from numerics. So in this example numerics are:

  • 983
  • 294
  • 343
  • 3546

And the MAX value is the last one - 3546. How to do this in TSQL on Microsoft SQL?

9 Answers 9

8

First install a regular expression function. This article has code you can cut/paste.

Then with RegexReplace (from that article) you can extract digits from a string:

dbo.RegexReplace( '.*?(\d+).*', myField, '$1' )

Then convert this string to a number:

CAST( dbo.RegexReplace( '.*?(\d+).*', myField, '$1' ) AS INT )

Then use this expression inside a MAX() function in a SELECT.

Sign up to request clarification or add additional context in comments.

5 Comments

If using SQL2005 or newer then I would probably handle the regex with a user-defined CLR function rather than wrapping an OLE object.
Although installing the regular expression function can be very useful, it is not necessary in this particular scenario, user defined function or CTE which uses patindex will sufice
1. My RegexReplace gets 5 arguments not 3: pattern, replacement, subject , global and multiline 2. I still get '4564a' for '4564a' and should have 4564, so it does not work in this form :(
3. When I replace myField with '$1' I get always last digit from my number only.
@tomaszs -- I had a bug, see the new code above. I added a '?' for a non-greedy accumulator in the first .* expression. That's why you got just one digit.
2

You can try to keep it simple without using Regular Expression alt text

Here is the source

create table #t ( val varchar(100) )
insert #t select 983
insert #t select 294
insert #t select 'a343'
insert #t select 'a3546f';
GO

;with ValueRange as (
    select  val,
        [from] = patindex('%[0-9]%', val), 
        [to] = case patindex('%[a-z]', val) 
            when 0 then len(val) 
            else patindex('%[a-z]', val) - patindex('%[0-9]%', val) 
               end
    from    #t
)
select  substring(val, [from], [to]) as val
from    ValueRange VR
order by cast(substring(val, [from], [to]) as int) desc

3 Comments

@tomaszs just add GO or ; before WITH
@Sung - I have added a semicolon before the WITH, I think that if you use the CTE in SQL 2005 with a batch of statements, the statement before the CTE definition must have a semicolon.
@kristof: You are right. I ran "create" & "insert" separately from "select" statement. I should have been more thorough when I posted the source. -- I have updated the source.
2

CAST() would do the trick, probably.

SELECT MAX(CAST(yourColumn AS int)) AS maxColumns FROM yourTable

Edit. I didn't read the whole question, as it seems...

– Function to strip out non-numeric chars
ALTER FUNCTION dbo.UDF_ParseNumericChars
(
  @string VARCHAR(8000)
)
RETURNS VARCHAR(8000)
AS
BEGIN
  DECLARE @IncorrectCharLoc SMALLINT
  –SET @IncorrectCharLoc = PATINDEX(’%[^0-9A-Za-z]%’, @string)
  SET @IncorrectCharLoc = PATINDEX(’%[^0-9.]%’, @string)
  WHILE @IncorrectCharLoc > 0
  BEGIN
    SET @string = STUFF(@string, @IncorrectCharLoc, 1, ”)
    SET @IncorrectCharLoc = PATINDEX(’%[^0-9.]%’, @string)
  END
  SET @string = @string
  RETURN @string
END
GO

I picked it from here. (I voted up the reg exp answer though)

2 Comments

Conversion failed when converting the varchar value '48a' to data type int.
Your original query helped me. I had 4 characters on the front that I stripped away using substring. Cheers.
1

you can write a function something like

create FUNCTION [dbo].[getFirstNumeric](
    @s VARCHAR(50)
)  
RETURNS int AS 
BEGIN

set @s = substring(@s,patindex('%[0-9]%',@s),len(@s)-patindex('%[0-9]%',@s) + 1) 
if patindex('%[^0-9]%',@s) = 0
    return @s
set @s = substring(@s,1,patindex('%[^0-9]%',@s)-1) 

return cast(@s as int)
end

and then call

select max(dbo.getFirstNumeric(yourColumn)) from yourTable

if you are using SQL Server 2005 or never you can also use the solution posted by Sung Meister

Comments

0

As far as I know you would need to create a process (or user defined function) to scrub the column, so that you can actually convert it to an INT or other appropriate datatype, then you can take the max of that.

2 Comments

No, it's possible without an external process.
True, my term "process" is misleading, your regex example is an awesome solution!
0

By using user defined function parse the value to an int and then run the select.

SELECT MAX(dbo.parseVarcharToInt(column)) FROM table

Comments

0
SELECT dbo.RegexReplace('[^0-9]', '','a5453b',1, 1)

and RegexReplace installation like Jason Cohen said

Comments

0

This is an old question, I know - but to add to the knowledge base for others...

Assuming all your values have at least 1 number in them:

Select max(convert(int, SubString(VarName, PATINDEX('%[0-9]%',VarName), Len(VarName))))
from ATable

Comments

0

This is my simple answer. You can try it. But it works for fixed removable string value.

select max(cast(SUBSTRING(T.column,3,len(T.column)) as int)) from tablename T

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.