select max value from a string column in SQL - sql-server

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

Related

DAX TOP 1 COUNT of GROUPBY

I want to have a Card in Power BI with the result of the select
SELECT TOP 1 [COLUMN] FROM [Table]
GROUP BY [COLUMN]
ORDER BY COUNT([COLUMN]) DESC
How can I do something like this in dax?
create in powerbi a new table by dax:
Top1 = TopN(1, VALUES(Table__[Column1]), Table__[CountOf], DESC)
where
CountOf = CountOf = count(Table__[Column1])
this is equivalent the maximum value of [COLUMN], that can be easily obtained with
MAX(Table[COLUMN])
another solution is using LASTNONBLANKVALUE
LASTNONBLANKVALUE(Table[COLUMN], Table[COLUMN])
that returns a scalar, otherwise LASTNONBLANK returns a table of a single row and a single column
LASTNONBLANK(Table[COLUMN], Table[COLUMN])
My problem was solved by making a
SingleLeads = DISTINCTCOUNT(Fact_ProductRequests[COLUMN])
I figure this out after checking that there were repeated values ​​in the column.
It was probably, the desperation that settled in not getting the results I wanted, that made me open this question.
Thank you all.

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

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.

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]%'

Select max int from varchar column

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

Resources