How to extract numbers(Integer) from String field in database and find the maximum - sql

I have an entity. One field named "number" consists of String. It is a number + some text information. For example:
131-MOD
11853-ARO
983-AKK
etc.
My task is: get the maximum of the first number. So, I have to extract Integer value from String "number" and find the maximum from it. For the examples higher, it would be the numbers 131, 11853 and 983. So, the maximum is 11853. I have to get this Integer value as a result.
Here i have my try using Hibernate. But it working with only Integer values. How to extract number, i have no idea.
public Integer getMaxNumber()
{
return (Integer) getSessionFactory().getCurrentSession().createQuery("select max(id) from EmployeeTripCard s").uniqueResult();
}
How can i do that?

You may use the following JPQL query:
SELECT
MAX(CAST(SUBSTRING(id, 1, LOCATE(id, '-') - 1) AS INTEGER))
FROM EmployeeTripCard s;
We can use LOCATE to find the index of the first -, then call SUBSTRING to find the initial number. Note carefully that we also need to cast this resulting string to an integer, in order for MAX to behave the way we want (numbers as text don't always sort the same way as actual pure numbers).

Related

How to get an accurate length of a long digit number in Oracle

I'm working with a schema (not created by me) that has calculated variances that can be really long numbers. I need to identify these long numbers so I can trunc them. The problem is that they are so long, the length function doesn't seem to recognize them as being long.
SELECT Length(10.00000000000000000000000000000000000004) FROM dual;
result: 2
Obviously the number above is longer than 2 digits, but the length function doesn't recognize this. How do I get an accurate length of this number, so I can find all the cases where they exist?
This happens because the length() function accepts a string as input, not a number, so the value is implicitly converted to a string using some default format before the function ever sees it.
There may be a more elegant mathematical solution, but one approach would be to use the 'text minimum' number format, length(to_char(num,'TM')):
with demo(num) as (select 10.00000000000000000000000000000000000004 from dual)
select to_char(num)
, to_char(num,'TM')
, length(to_char(num,'TM'))
from demo;
TO_CHAR(NUM) TO_CHAR(NUM,'TM') LENGTH(TO_CHAR(NUM,'TM'))
------------- ----------------------------------------- -------------------------
10 10.00000000000000000000000000000000000004 41

SQL order by integer within a string

I have a string that my result is sorting by. It is composed of a room number, resident name, and a few other fields.
Example:
460, Bob Jones, ......
5, John Doe, .....
The problem is, when I order this way, it puts large numbers that begin with a small number ahead of the small numbers that begin with a large one (ie, 460 is placed before 5). How can I have sql process the entire integer in the string and sort based on the entire number, not just the first digit value?
You can do this by converting the initial part of the string to a number. However, this depends on the database. For instance, in MySQL, you can convert the value to an integer just by adding + 0:
order by string + 0
In other databases, you would need to part up to the comma and do a conversion. For instance, in SQL Server:
order by cast(left(string, charindex(',', string) - 1) as int)

How do I perform a LIKE query on a PostgreSQL primary id column?

If I have a number (such as 88) and I want to perform a LIKE query in Rails on a primary ID column to return all records that contain that number at the end of the ID (IE: 88, 288, etc.), how would I do that? Here's the code to generate the result, which works fine in SQLLite:
#item = Item.where("id like ?", "88").all
In PostgreSQL, I'm running into this error:
PG::Error: ERROR: operator does not exist: integer ~~ unknown
How do I do this? I've tried converting the number to a string, but that doesn't seem to work either.
Based on Erwin's Answer:
This is a very old question, but in case someone needs it, there is one very simple answer, using ::text cast:
Item.where("(id::text LIKE ?)", "%#{numeric_variable}").all
This way, you find the number anywhere in the string.
Use % wildcard to the left only if you want the number to be at the end of the string.
Use % wildcard to the right also, if you want the number to be anywhere in the string.
Simple case
LIKE is for string/text types. Since your primary key is an integer, you should use a mathematical operation instead.
Use modulo to get the remainder of the id value, when divided by 100.
Item.where("id % 100 = 88")
This will return Item records whose id column ends with 88
1288
1488
1238872388
862388
etc...
Match against arbitrary set of final two digits
If you are going to do this dynamically (e.g. match against an arbitrary set of two digits, but you know it will always be two digits), you could do something like:
Item.where(["id % 100 = ?", last_two_digits)
Match against any set or number of final digits
If you wanted to match an arbitrary number of digits, so long as they were always the final digits (as opposed to digits appearing elsewhere in the id field), you could add a custom method on your model. Something like:
class Item < ActiveRecord
...
def find_by_final_digits(num_digits, digit_pattern)
# Where 'num_digits' is the number of final digits to match
# and `digit_pattern` is the set of final digits you're looking fo
Item.where(["id % ? = ?", 10**num_digits, digit_pattern])
end
...
end
Using this method, you could find id values ending in 88, with:
Item.find_by_final_digits(2, 88)
Match against a range of final digits, of any length
Let's say you wanted to find all id values that end with digits between 09 and 12, for whatever reason. Maybe they represent some special range of codes you're looking up. To do this you could do another custom method to use Postgres' BETWEEN to find on a range.
def find_by_final_digit_range(num_digits, start_of_range, end_of_range)
Item.where(["id % ? BETWEEN ? AND ?", 10**num_digits, start_of_range, end_of_range)
end
...and could be called using:
Item.find_by_final_digit_range(2, 9, 12)
...of course, this is all just a little crazy, and probably overkill.
The LIKE operator is for string types only.
Use the modulo operator % for what you are trying to do:
#item = Item.where("(id % 100) = ?", "88").all
I doubt it "works" in SQLite, even though it coerces the numeric types to strings. Without leading % the pattern just won't work.
-> sqlfiddle demo
Cast to text and use LIKE as you intended for arbitrary length:
#item = Item.where("(id::text LIKE ('%'::text || ?)", "'12345'").all
Or, mathematically:
#item = Item.where("(id % 10^(length(?)) = ?", "'12345'", "12345").all
LIKE operator does not work with number types and id is the number type so you can use it with concat
SELECT * FROM TABLE_NAME WHERE concat("id") LIKE '%ID%'

MS Access SQL, Rnd Function without numeric field

Is it possible in a Microsoft Access query to use the Rnd() Function without specifying a numeric column (e.g. when my Primary Key contains Alpha characters) and still generate a different random number for each row?
You could use the 1st character;
rnd(asc(left([field],1)))
which should give a different result for each row, even if the char is the same
It's simpler than I originally thought, this function can be used in exactly the same context as Rnd()
Public Function Rand(FieldName) As Single
Rand = Rnd(1)
End Function
Then in SQL used as:
SELECT ID, Rand([ID]) FROM Table
By passing it a fieldname, we force the function to execute for each row in the query (eventhough we ignore the actual field in the function) and then evaluating the function to 1 will always return a different random number in the same way Rnd() would if executed in VB.

How to find MAX() value of character column?

We have legacy table where one of the columns part of composite key was manually filled with values:
code
------
'001'
'002'
'099'
etc.
Now, we have feature request in which we must know MAX(code) in order to give user next possible value, in example case form above next value is '100'.
We tried to experiment with this but we still can't find any reasonable explanation how DB2 engine calculates that
MAX('001', '099', '576') is '576'
MAX('099', '99', 'www') is '99' and so on.
Any help or suggestion would be much appreciated!
You already have the answer to getting the maximum numeric value, but to answer the other part with regard to 'www','099','99'.
The AS/400 uses EBCDIC to store values, this is different to ASCII in several ways, the most important for your purposes is that Alpha characters come before numbers, which is the opposite of Ascii.
So on your Max() your 3 strings will be sorted and the highest EBCDIC value used so
'www'
'099'
'99 '
As you can see your '99' string is really '99 ' so it is higher that the one with the leading zero.
Cast it to int before applying max()
For the numeric maximum -- filter out the non-numeric values and cast to a numeric for aggregation:
SELECT MAX(INT(FLD1))
WHERE FLD1 <> ' '
AND TRANSLATE(FLD1, '0123456789', '0123456789') = FLD1
SQL Reference: TRANSLATE
And the reasonable explanation:
SQL Reference: MAX
This max working well in your type definition, when you want do max on integer values then convert values to integer before calling MAX, but i see you mixing max with string 'www' how you imagine this works?
Filter integer only values, cast it to int and call max. This is not good designed solution but looking at your problem i think is enough.
Sharing the solution for postgresql
which worked for me.
Suppose here temporary_id is of type character in database. Then above query will directly convert char type to int type when it gives response.
SELECT MAX(CAST (temporary_id AS Integer)) FROM temporary
WHERE temporary_id IS NOT NULL
As per my requirement I've applied MAX() aggregate function. One can remove that also and it will work the same way.