SQL order by integer within a string - sql

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)

Related

Working with Strings to convert to numeric value with range

I am working with the Texas business email dataset and i want to target all companies that have 25 to 300 employees. The Schema is currently setup with the employee count as a string with values like Employee_count: "25 to 300" "1 to 100" etc and others simply a single digit like Employee_Count: "10" , "3,000" etc. Is there a way for me to first parse the string so that it converts both numbers into a numeric range, Or at least get the larger of the two numbers, so that i can grab companies by employee count ranges?
I tried using CAST, JSON_FUNCTIONS etc but i am also fairly new to SQL so any tips would be greatly appreciated.
The end result im trying to get is to get a list of employers with 25 to 300, 301 to 1,000.
You want to split the string at the "to" position. Trim all spaces and remove all ,. Since the clean up will be used twice, we create a tempory function.
create temp function help_parse(str string) as (
safe_cast(replace(trim(str),",","") as int64)
);
with tbl as (Select * from unnest(["25 to 300","1 to 100" ,"10","3,000","1200"]) Employee_count)
select * ,
help_parse(split(Employee_count,"to")[safe_offset(0)]) as Employee_count_low,
help_parse(split(Employee_count,"to")[safe_offset(1)]) as Employee_count_high,
from tbl

How to retrieve the required string in SQL having a variable length parameter

Here is my problem statement:
I have single column table having the data like as :
ROW-1>> 7302-2210177000-XXXX-XXXXXX-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-U-XXXXXXXXX-XXXXXX
ROW-2>> 0311-1130101-XXXX-000000-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-X-XXXXXXXXX-WIPXXX
Here i want to separate these values from '-' and load into a new table. There are 11 segments in this string separated by '-', therefore, 11 columns. The problem is:
A. The length of these values are changing, however, i have to keep it as the length of these values in the standard format or the length which it has
e.g 7302- (should have four values, if the value less then that then keep that value eg. 73 then it should populate 73.
Therefore, i have to separate as well as mentation the integrity. The code which i am writing is :
select
SUBSTR(PROFILE_ID,1,(case when length(instr(PROFILE_ID,'-')<>4) THEN (instr(PROFILE_ID,'-') else SUBSTR(PROFILE_ID,1,4) end)
)AS [RQUIRED_COLUMN_NAME]
from [TABLE_NAME];
getting right parenthesis error
Please help.
I used the regex_substr SQL function to solve the above issue. Here below is an example:
select regex_substr('7302-2210177000-XXXX-XXXXXX-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-U-XXXXXXXXX-XXXXXX ROW-2>> 0311-1130101-XXXX-000000-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-X-XXXXXXXXX-WIPXXX',[^-]+,1,1);
Output is: 7302 --which is the 1st segment of the string
Similarly, the send string segment which is separated by "-" in the string can be obtained by just replacing the 1 with 2 in the above query at the end.
Example : select regex_substr('7302-2210177000-XXXX-XXXXXX-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-U-XXXXXXXXX-XXXXXX ROW-2>> 0311-1130101-XXXX-000000-XXX-XXXXXXXXXX-XXXXXX-XXXXXX-X-XXXXXXXXX-WIPXXX',[^-]+,1,2);
output: 2210177000 which is the 2nd segment of the string

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

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).

SQL Server - Combine string to integer where integer can have a variable number of leading zeros

I have a report in SQL Server Report Builder which brings back the profession acronym (string) and registration number (integer) for each professional in a separate SQL database.
The registration number can be 5 or more digits long, and may start with one or more zeros. For example:
Profession Registration #
AB 00162
PH 02272
SA 13925
SA 026025
DA 1025927
I'm trying to put the profession acronym and registration number together into a registration ID, because I need to compare this with the registration ID from another (non SQL) database.
I'm trying to get something like this:
Registration ID
AB00162
PH02272
SA13925
SA026025
DA1025927
I've tried converting the integers to strings using the following in my query:
REGISTRY.PROFESSION + right('00000' + cast(REGISTRY.REGISTRATION_NO as varchar(8)), 5) as Full_Reg_Number
However, with the above the integers that are more than 5 digits long get cut off, and if I increase '00000' to, say, '0000000' and the number '5' to '7' in the above, the integers that only have 5 digits are padded with extra leading zeros.
I do not have permission to change the formatting of the integers in either database.
Integers aren't stored with leading zeroes. To be stored like that, then the field is NOT of integer type in the first place. Simply do:
Registry.profession + registry.registration_no
You can confirm that the stored type is not an integer as follows:
select data_type
from information_schema.columns
where table_name = 'registry'
and column_name = 'registration_no'
If you're getting a type conversion error as you mention in your comments, then most likely the error is not coming due to this concatenation. It's probably down the line, such as if you're using 'Full_Reg_Number' in a 'where' statement or other comparison that expects a comparison to an integer, and instead is getting a varchar. After all, you called the column 'Full_Reg_Number' even though it's not a number.
Based on your problems, I suspect those really are integers. You've just shown them with leading zeros in the question.
A simple solution is to use case:
(REGISTRY.PROFESSION +
CASE WHEN REGISTRY.REGISTRATION_NO < 10000 THEN right('00000' + cast(REGISTRY.REGISTRATION_NO as varchar(8)), 5)
ELSE REGISTRY.REGISTRATION_NO
END
) as Full_Reg_Number
An even simpler method uses FORMAT():
(REGISTRY.PROFESSION + FORMAT(REGISTRY.REGISTRATION_NO, '00000')
) as Full_Reg_Number

How to implement MAX function on a text column in SQL Server?

I'm using SQL Server 2005 and have a column that contains serial numbers, which are nvarchar(50).
My problem is selecting max(serial_no) from the table. The serial numbers used to have a length of 7 only but new ones are now 15. Whenever I select the max, I get a result with a length of 7, which means that data is old. I also can't filter it to only select from records which have a length of 15 because then i'll miss some other data on my query.
Old serial numbers look like this...
'SNGD001'
..., and new ones look like this:
'SN14ABCD0000001'
Edit: I tried creating a dummy table without the old serial numbers (5 characters long), and I'm getting correct results.
As has been mentioned, your question is a bit hard to follow. If the max value could be either one of your old serial numbers or one of your new ones, I believe the following should do the trick:
SELECT MAX(RIGHT('0000000' + REVERSE(LEFT(REVERSE(YourTextColumn), PATINDEX('%[a-z]%', REVERSE(YourTextColumn)) - 1)), 7))
FROM YourTable
It finds the first non numeric character from the right keeping everything to the right of that. It then left zero pads the resulting numeric string to 7 characters and applies the MAX function.
Your question is a little tough to follow without good sample data to get a bearing on. I suggest for future, you show a few more examples of data to get better context, especially with sequencing. Now, your desire to get the MAX() of a "serial_no" from your table appears you need so you get detect the next sequential serial number to assign. However, your serial number appears to be a concatenation of a prefix string and then sequential. So, if I were to look at your brief data MIGHT HAVE BEEN along the lines of (last 3 digits are the sequential serializations)
SNGD001
SNGD002
SNGD003
...
SNGD389, etc...
and your new data with the last (last 7 digits are sequential serializations)
SN14ABCD0000001
SN14ABCD0000002
SN14ABCD0000003
...
SN14ABCD0002837
If this is correct, then you basically need to look at the max based on the leading 3 or 8 characters of the string PLUS the converted suffix numeric sequence. For starters, lets go with that to see if we are on the correct track or not, then you can easily concatenate the prefix and sequence number together at the end for determining the next available number.
So, based on the above samples, you may want to know that for each prefix, the last number of
SNGD389 and
SN14ABCD0002837 respective per their prefix
If the above is correct, I might start with...
select
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix,
MAX( case when LEN( RTRIM( yt.serial_no )) = 7
then CONVERT(INT, RIGHT( yt.serial_no, 3 ))
else CONVERT(INT, RIGHT( yt.serial_no, 7 )) end ) as SerialSequence
from
YourTable yt
group by
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix
Which would result in (based on sample data I presented)
SerialPrefix SerialSequence
SNGD 389
SN14ABCD 0002837
Of which since the serial sequence column being numeric, you could add 1 to it, then left-zero fill a string and concatenate the two back together such as to create
SNGD390
SN14ABCD0002838