Select max int from varchar column - sql-server

I am trying to retrieve the largest number from a varchar column that includes both numbers and strings. An example of the data I'm working with:
BoxNumber
123
A5
789
B1
I need to return the largest number (789 in this case) from the column while ignoring the non-numeric values of A5 and B1.
I have found solutions that use custom functions to solve the problem, but I need something that can be executed ad-hoc query without relying on custom functions or procs.

you need a combination because of the fact that isnumeric returns 1 for the following things
select isnumeric('+'),isnumeric('5d2')
your where clause would be like this
WHERE VALUE NOT LIKE '%[a-z]%'
AND ISNUMERIC(VALUE) = 1
create table #bla (value varchar(50))
insert #bla values('123')
insert #bla values('a5')
insert #bla values('789')
insert #bla values('b1')
SELECT MAX(CAST(value AS Int)) FROM #bla
WHERE VALUE NOT LIKE '%[a-z]%'
AND ISNUMERIC(VALUE) = 1
I wrote about this here ISNUMERIC Trouble

You might try
Select MAX(BoxNumber) from {table} where IsNumeric(BoxNumber) = 1

Why not
SELECT MAX(CAST(Value AS Int)) FROM #bla
WHERE ISNUMERIC(Value)=1
AND Value LIKE '%[0-9]%'
then you're only dealing with numeric strings. In this case you may not need ISNUMERIC()

The selected answer worked for me until I added this value to the temp table along with the others in the sample:
insert #bla values('1234')
I expected my max() result to now be 1234, but it remained at 789. Perhaps this is due to some collation setting, but I was able to reproduce on multiple databases. I found this query below worked for me, but I'd certainly be interested to hear if there is a more efficient way of doing this. Also, I did not want to include any decimal values, so I excluded anything with a period as well.
SELECT MAX(CAST(Value AS Int)) FROM #bla
WHERE ISNUMERIC(Value)=1
AND Value NOT LIKE '%[a-z]%'
AND Value NOT LIKE '%.%'

You should check this solution out for values like '+' and '-' as I think the IsNumeric function may return 1 for these values

Well, in the intervening 11 years since this question was asked, SQL Server gained the try_cast function, which returns null rather than throwing an error if the conversion doesn't succeed. So in current versions of SQL Server, a valid answer is
select max(try_cast(BoxNumber as int)) from theTable

Look into casting the column to an int, then selecting the MAX(). I don't know what it will do to columns that contain letters, but it's worth exploring.
http://doc.ddart.net/mssql/sql70/ca-co_1.htm

These answers are only half right. They succeed in isolating numeric values, but don't realize that when the underlying field is a number the Max function evaluates as characters (regardless of casting), reading left to right, so that 789 > 1000 because 7 > 1. A way around this might be to forget about casting and left pad the numbers with zeros to a common length, when Max in character mode should work.

SELECT MAX(CAST(value as signed)) FROM yourTable
WHERE VALUE NOT LIKE '%[a-z]%'
AND ISNUMERIC(VALUE) = 1
In MySql
You should use signed instead of int to cast correctly.
P.s types used to cast may differ in MySql
For more conversions visit this link

select max(cast(column as numeric)) from table
Where column was varchar which was casted to numeric in postgresql

Related

Separating Numeric Values from string

I'm having an issue, whereby I need to separate the following BPO007 to show BPO and 007. In some cases another example would be GFE0035, whereby I still need to split the numeric value from the characters.
When I do the following select isnumeric('BPO007') the result is 0, which is correct, however, I'm not sure how split these from each other.
I've had a look at this link, but it does not really answer my question.
I need the above split for a separate validation purpose in my trigger.
How would I develop something like this?
Thank you in advance.
As told in a comment before:
About your question How would I develop something like this?:
Do not store two pieces of information within the same column (read about 1.NF). You should keep separate columns in your database for BPO and for 007 (or rather an integer 7).
Then use some string methods to compute the BPO007 when you need it in your output.
Just not to let you alone in the rain.
DECLARE #tbl TABLE(YourColumn VARCHAR(100));
INSERT INTO #tbl VALUES('BPO007'),('GFE0035');
SELECT YourColumn,pos
,LEFT(YourColumn,pos) AS CharPart
,CAST(SUBSTRING(YourColumn,pos+1,1000) AS INT) AS NumPart
FROM #tbl
CROSS APPLY(SELECT PATINDEX('%[0-9]%',YourColumn)-1) AS A(pos);
Will return
YourColumn pos CharPart NumPart
BPO007 3 BPO 7
GFE0035 3 GFE 35
Hint: I use a CROSS APPLY here to compute the position of the first numeric character and then use pos in the actual query like you'd use a variable. Otherwise the PATINDEX would have to be repeated...
Since the number and text varies, you can use the following codes
DECLARE #NUMERIC TABLE (Col VARCHAR(50))
INSERT INTO #NUMERIC VALUES('BPO007'),('GFE0035'),('GFEGVT003509'),('GFEMTS10035')
SELECT
Col,
LEFT(Col,LEN(Col)-LEN(SUBSTRING(Col,PATINDEX('%[0-9]%',Col),DATALENGTH(Col)))) AS TEXTs,
RIGHT(Col,LEN(Col)-LEN(LEFT(Col,LEN(Col)-LEN(SUBSTRING(Col,PATINDEX('%[0-9]%',Col),DATALENGTH(Col)))))) AS NUMERICs
FROM #NUMERIC

select max value from a string column in SQL

I have table with a column Order of type varchar as follows
Order
-----
Ord-998,
Ord-999,
Ord-1000,
Ord-1001,
I want to get the max value as 1001
But when I run this query, I am getting 999 as max value always
select
SUBSTRING((select isnull(MAX(OrderNo), '0000000')
from OrderSummary
where OrderNo like 'Ord%'), 5, 10) as [OrderMax]
Can anybody provide a solution?
Since you are maxing a string it is sorting alphabetically where C is larger than AAA and 9 is larger than 10. Remove the letters and cast it as an int then get the max. Given that it will always be Ord-### we can remove the Ord- and cast the remainder as an INT.
SELECT
MAX(CAST(SUBSTRING(OrderNo,5,LEN(OrderNo)-4) AS INT))
FROM OrderSummary
WHERE OrderNo LIKE 'Ord-%'
Another possibility would be the REPLACE-function:
SELECT
MAX(CONVERT(int,(REPLACE(OrderNo, 'Ord-' ,'')))) AS OrderMax
FROM OrderSummary;
But like already mentioned in comments, the best solution will be to get rid of the "Ord-" and create a int-column instead.
If I were tackling this issue I would Order Number as an integer instead of a varchar, and not store the repetitive text "Ord-" in the field. If end users require "Ord-998", I'd handle it via my CRUD layer.
This also allows you to declare the Order Number column as an identity column, which will handle the automatic incrementing for you.
Please try this query in SQL Server
select MAX(convert(int, substring(orderno, 5, LEN(orderno))))
from OrderSummary
I attach another possible solution this query is posgresQL
SELECT
CONCAT(RPAD('Ord-',5), MAX(CAST(SUBSTRING(OrderNo,5,length(OrderNo)-4) AS INT)))AS
ORDER
FROM OrderSummary
RESULT
Order
Ord-1001
Use len keyword instead of like keyword
select MAX(CAST(SUBSTRING(OrderNo, 6, len(OrderNo)) AS INT)) FROM OrderSummary
The problem, as stated in other answers is that you have a string. I will provide here an alternative solution: you could select top 1 from your table and have an order by len(OrderNo) desc, OrderNo desc. This way you will not have to cut all the varchars and convert them to integer, but will be able to simply compare their length (very quick) and if similar, their varchar value (pretty slow). Of course, a default for null values is a good idea, but make sure you do not put more 0-s there than the number of digits of your first number.
u can cast as int,it will consider value,not lexic. order
ie.
max(cast(Col as int)) from Table

Using "CAST" operator in sql with where and IN clause not working

The right query that works fine is
select * from Pretty_Txns where Send_Customer in ('1000000000164774783','1000000000253252111')
But I have data coming from outside SQL from a python application which is of the below format and of a varying length and hence the use of IN clause as it can be easily parameterised
(1000000000164774783,1000000000253252111)
So , I am trying to use a CAST operator to make life simple
select * from Pretty_Txns where cast (Send_Customer as numeric) in(1000000000164774783,1000000000253252111)
But it fails with:
Arithmetic overflow error converting varchar to data type numeric.
select * from Pretty_Txns where cast (Send_Customer as bigint) in(1000000000164774783,1000000000253252111)
Error converting data type varchar to bigint.
select * from Pretty_Txns where cast (Send_Customer as numeric(38)) in(1000000000164774783,1000000000253252111) --default total digits is 18 if not specified
or
select * from Pretty_Txns where cast (Send_Customer as bigint) in(1000000000164774783,1000000000253252111)
Updated:
First to check whether there are all numeric types of records in Send_Customer
This will give you all the records that contain only numbers,
SELECT Send_Customer FROM yourTable WHERE Send_Customer NOT LIKE '%[^0-9]%
or you could run the following two to compare:
1:
select Count(*)
from (
SELECT Send_Customer
FROM yourTable
WHERE Send_Customer NOT LIKE '%[^0-9]%'
) as ABC
2:
select count(Send_Customer)
from yourtable
Compare the result number with the total you have in table, if does not match, there must be some containing non numeric characters, then it cannot do the convert from varchar(..)(I assume it is varchar here) to numeric, unless you have take care of those records first, such as replace other characters, delete other characters using REPLACE or STUFF, but it will bring the data loss, which may not be accurate in your case.
You could also cast the individual values in the IN clause to varchar if there were only a few, instead of casting the DB field. That way, you wouldn't get a conversion error if send_customer contained some non-numeric data.
Just adding this in case anyone else comes across it in Google.

SQL INSERT using tables where the columns have different data types and getting error converting

I have two tables and I would like to insert from one into the other. In my staging (source) table every column is defined as nvarchar(300) and this restriction cannot change.
In my destination table, the columns are of all different types. If I want to, for example, select from the source table (data type nvarchar(300)) and insert that column into a data type of decimal(28, 16).
When this happens I get the following error:
Error converting data type nvarchar to numeric.
Even when I use a cast I get the error.
INSERT INTO Destination (
Weighting
)
VALUES (
CAST(src.Weighting AS decimal(28, 16))
)
Could null values be affecting this at all? Is there anything else to consider?
If all data in your staging table column can be implicitly converted to the target data type then you do not have to set up an explicit cast.
But if any one value cannot be converted implicitly (i.e. one cell contains a non-numeric or ill-formatted string value that is supposed to end up in a decimal type column) then the entire transaction will fail.
You can migrate the risk of a failing transaction by setting up the insert like this:
INSERT
LiveTable (
VarcharCol,
DecimalCol,
NonNullableCol
)
SELECT
NvarcharCol1,
CASE ISNUMERIC(nvarcharCol2) = 0 THEN NvarcharColl2 END,
ISNULL(NvarcharCol3, '')
FROM
StagingTable
But clearly that means the risk of losing potentially relevant data or numeric precision.
You can read which data types are implicitly convertible between each other on the MSDN (scroll down to the matrix). For all other conversions you'll have to use CAST or CONVERT.
This will search for non numeric strings
select src.Weighting from src where isnumeric(src.Weighting) = 0
INSERT INTO Destination (Weighting)
SELECT CAST(src.Weighting AS decimal(28, 16))
FROM [Source] src
should work OK, provided your varchar values are in correct format.
If the error still occurs, please give an example of value being converted.
NULLs will successfully convert to NULLs.
TSQL has functions for casting or converting data to the type you want it to be. If your data types in the source are strictly what you are trying to store them as in the destination table and with in the specifications of the destination table you won't have much trouble.
If you have a column of numbers and one of the is 'three' instead of '3' it gets complicated. Here is a question about converting a varchar to a decimal
An example: I can cast 123 as a varchar(20) then cast the varchar into a decimal with no problem when it is appropriate.
SELECT cast(cast('123' as varchar(20)) as decimal(8,2))
However if I try to convert a character it will give an error.
SELECT cast(cast('1a3' as varchar(20)) as decimal(8,2))
The null only be a problem if the target column does not allow nulls, I think the problem is that the format string that can not always be converted into a decimal, see if the decimal separator is a comma instead of a point.

How would I determine if a varchar field in SQL contains any numeric characters?

I'm working on a project where we have to figure out if a given field is potentially a company name versus an address.
In taking a very broad swipe at it, we are going under the assumption that if this field contains no numbers, odds are it is a name vs. a street address (we're aiming for the 80% case, knowing some will have to be done manually).
So now to the question at hand. Given a table with, for the sake of simplicity, a single varchar(100) column, how could I find those records who have no numeric characters at any position within the field?
For example:
"Main Street, Suite 10A" --Do not return this.
"A++ Billing" --Should be returned
"XYZ Corporation" --Should be returned
"100 First Ave, Apt 20" --Should not be returned
Thanks in advance!
Sql Server allows for a regex-like syntax for range [0-9] or Set [0123456789] to be specified in a LIKE operator, which can be used with the any string wildcard (%). For example:
select * from Address where StreetAddress not like '%[0-9]%';
The wildcard % at the start of the like will obviously hurt performance (Scans are likely), but in your case this seems inevitable.
Another MSDN Reference.
select * from table where column not like '%[0-9]%'
This query returns you all rows from table where column does not contain any of the digits from 0 to 9.
I like the simple regex approach, but for the sake of discussion will mention this alternative which uses PATINDEX.
SELECT InvoiceNumber from Invoices WHERE PATINDEX('%[0-9]%', InvoiceNumber) = 0
This worked for me .
select total_employee_count from company_table where total_employee_count like '%[^0-9]%'
This returned all rows that contains non numeric values including 2-3 ..
This Query to list out Tables created with numeric Characters
select * from SYSOBJECTS where xtype='u' and name like '%[0-9]%'

Resources