views:

1701

answers:

7

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?

A: 

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.

Mitchel Sellers
No, it's possible without an external process.
Jason Cohen
True, my term "process" is misleading, your regex example is an awesome solution!
Mitchel Sellers
A: 

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)

Björn
does that work with leading characters as in the example?
Jason Cohen
This would not work with the leading and trailing values
Mitchel Sellers
Conversion failed when converting the varchar value '48a' to data type int.
tomaszs
Maybe I should have read the whole question before I answered...
Björn
+1 for correction :)
tomaszs
A: 

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

SELECT MAX(dbo.parseVarcharToInt(column)) FROM table
Rashack
+8  A: 

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.

Jason Cohen
If using SQL2005 or newer then I would probably handle the regex with a user-defined CLR function rather than wrapping an OLE object.
LukeH
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
kristof
1. My RegexReplace gets 5 arguments not 3: pattern, replacement, subject , global and multiline2. I still get '4564a' for '4564a' and should have 4564, so it does not work in this form :(
tomaszs
3. When I replace myField with '$1' I get always last digit from my number only.
tomaszs
wow that's awesome. thanks for this trick!
DrG
@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.
Jason Cohen
Thank you Jason. Now it works fine!
tomaszs
+1  A: 

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

kristof
+2  A: 
Sung Meister
And I have: Incorrect syntax near 'ValueRange'. (SQL 2005)
tomaszs
@tomaszs just add GO or ; before WITH
kristof
@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
Sung Meister
@tomaszs: you're welcome.
Sung Meister
A: 
SELECT  dbo.RegexReplace('[^0-9]', '','a5453b',1, 1)

and RegexReplace installation like Jason Cohen said

tomaszs