Sorting varchar column by number, character [duplicate] - sql

This question already has answers here:
How to do sorting on irregular Alphanumeric data in postgres sql
(2 answers)
Closed 10 years ago.
I have a varchar column [flat_number] which has some values as
A1A1A
A1A2A
A1A101A
A3A5A
12
A2
A3
I wish to get the results sorted by number and then by characters first
like
12
A2
A3
A1A1A
A1A2A
A1A101A
A3A5A
I have managed to sort it by number (if the column only contains digits 0-9 using regex, I treat it as a number), then I sort it by character, but it dosent seem to work for column values as A1A101A (having multiple combinations of number and character)
CASE
WHEN length(flat_number) < 10 AND flat_number SIMILAR TO '[0-9]+'
THEN
flat_number::int
END
ELSE
NULL
END,
( SELECT COALESCE( match[1], NULL ) FROM regexp_matches( flat_number, '[^0-9]+' ) AS match ),
( SELECT COALESCE( left( match[1], 9), NULL ) FROM regexp_matches( flat_number, '([0-9]+$)' ) AS match )::int
The current query works as
If the column contains only numbers [0-9] I convert it to int and sort it
ElSE, I split the column into 2 parts and try to extract the column character at the start and the number at the end.
Is there a better wait to do so and also make sure the expected output is returned

I think the following will work:
order by (case when flat_number ~ '^[0-9]+$' then 0 else 1 end),
(case when flat_number ~ '^[0-9]+$' then length(flat_number) end),
flat_number
This orders the number first, uses a trick to put them in numeric order, and then orders the rest of the numbers.

Related

How to add a leading 0 in sql-server [duplicate]

This question already has answers here:
Pad a string with leading zeros so it's 3 characters long in SQL Server 2008
(18 answers)
Closed 10 months ago.
I have to add a leading 0 in a column called houses, where it is a unique list of 3 digits, but I wanted have to add a leading 0 to it --> so 4 digits instead of 3.
Can someone help me with this query as the code is incompatible in the '|' operator.
The code is as follows:
select houses from house_numbers
order by houses;
select houses,
case
when len(houses)=3 then '0' | houses
when len(houses)=4 then '' | houses
end as houses
from house_numbers
The string concatenation operator in SQL Server is +, not ||, so you should use:
CASE
WHEN LEN(houses) = 3 THEN '0' + houses
WHEN LEN(houses) = 4 THEN '' + houses
END AS houses
However, a better way to do this would be to just left pad with zero to a length of 4:
RIGHT('0000' + ISNULL(houses, ''), 4) AS houses
You are looking for the CONCAT function here, assuming you are dealing with varchars
when len(houses)=3 then CONCAT('0' , houses)
You could simplify like so
select houses from house_numbers
order by houses;
select houses,
case
when len(houses)=3 then CONCAT('0' , houses)
else houses
end as houses
from house_numbers
Always add the Zero and then strip of the right 4 chars, I believe this might be less resource intensive than doing a case
SELECT RIGHT('0'+CONVERT(VARCHAR(10),345),4) AS Three_Digit_Example,
RIGHT('0'+CONVERT(VARCHAR(10),1345),4) AS Four_Digit_Example

sql query about string function

ID MOBILE
1 9869600733
2 9869600793
3 9869600799
all id whose mobile number containing 9 three times(using string functions like replace, substr, etc)... ? (without like , % , etc)
You can use LEN and Replace
Where len(MOBILE)-len(replace(MOBILE ,'9',''))>=3
Note : Some DBMS uses LENGTH instead of LEN
Where length(MOBILE)-length(replace(MOBILE ,'9',''))>=3
DEMO
replace(MOBILE ,'9','') will replace all the 9's with empty
string
length(MOBILE) will count the number of characters in Mobile
column
length(replace(MOBILE ,'9','')) will count the number of characters
in Mobile column as replacing 9's with empty string
length(MOBILE)-length(replace(MOBILE ,'9','')) here the
difference will tell the number of missing characters that is our 9, you can use this difference to count the 9
exactly three '9's:
Select * from mytable
Where len(mobile) - len(replace(mobile, '9', '')) = 3
at least three '9's:
Select * from mytable
Where len(mobile) - len(replace(mobile, '9', '')) >= 3

Prepend 0s to string (to specific length) [duplicate]

This question already has answers here:
Formatting Numbers by padding with leading zeros in SQL Server
(14 answers)
Closed 9 years ago.
I have a query where I'm pulling in a check number from the database. The return value needs to always be 9 characters exactly. Most of the check numbers are only 6 characters, so I want to prepend 0s to to the string to ensure it is always exactly 9 characters. Since the check numbers can vary in length, it will be a different number of 0s for each one. What's the most efficient way to do this?
If they're always between 6 and 9 digits, the easiest (and probably best) way to go is using CASE.
SELECT CASE WHEN LEN(CHECK_NUM)= 6 THEN '000' WHEN LEN(CHECK_NUM) = 7 THEN '00'
WHEN
LEN(CHECK_NUM) = 8 THEN '0' ELSE '' END + CHECK_NUM
FROM TABLE
EDIT
In case the original values are numbers (int), try something like this:
SELECT CASE WHEN LEN(CHECK_NUM)= 6 THEN '000' WHEN LEN(CHECK_NUM) = 7 THEN '00'
WHEN
LEN(CHECK_NUM) = 8 THEN '0' ELSE '' END + CAST(CHECK_NUM AS VARCHAR(9))
FROM TABLE1
Take a look at the this SQL Fiddle.

Sorting a varchar column as integer value in Oracle query

I have a column DOOR which is a VARCHAR2 in a Table ADDRESS. I want to sort the column DOOR.
DOOR contains only two digits and no - sign
currently when I use the query
select sname, door, zip from address a order by door
I get the following result:
a
b
1
10
11
2
3
31
But I want the result to look like this:
a
b
1
2
3
10
11
31
I tried to convert DOOT into a numeric value using to_number as
select sname, to_number(door) dnr, zip from address a order by dnr
but it is giving me an error ORA-01722.
You can do this with the logic in the order by:
order by (case when regexp_like(door, '^[0-9]*$') = 0 then 1 else 0 end) desc,
(case when regexp_like(door, '^[0-9]*$') = 0 then door end),
length(door),
door
This first puts the non-numeric values first. The second clauses sorts these alphabetically. The third and fourth are for numbers. By sorting for the length before the value, you will get the numbers in order.
ORA-01722 error coming because of value 'a' ,'b',
Go for custom function which will take varchar and return number to convert , use custom function in order by clause of your query.
CREATE OR REPLACE FUNCTION tonumber (no_str varchar2)
RETURN number IS
num number := 0;
BEGIN
RETURN to_number(no_str);
EXCEPTION -- exception handlers begin A < B < 1 < 2
WHEN value_error THEN -- handles all other errors
dbms_output.put_line('in other exception catch.');
CASE
WHEN ( upper(no_str) = 'B' ) THEN return -1;
WHEN ( upper(no_str) ='A') THEN return -2;
ELSE return -999;
END CASE;
END;
Add when condition as in required. now assumed it can have only A B. for rest it will return default.
(This approach assumes that there aren't any mixed values like "234abc567".)
So, going old school...just 0-pad the strings to the maximum length of the column so that they'll sort properly as characters. But, to get the "non-numeric" values to sort first, nullify non-numeric values, put the NULLs first and padded values after that.
select door
from address
order by case when replace(translate(door, '012345679', '0000000000'), '0', '') is null
then lpad(door, 10, '0') -- value was entirely made of digits (change the 10 to the max width of the column)
else null
end nulls first
, door -- sorting within the group of NULL rows generated in the previous expression.
use the below query
SELECT PUMP_NAME
FROM MASTER.PUMPS
ORDER BY LPAD(PUMP_NAME, 10);

splitting strings in oracle sql based on length

I want to split my strings in Oracle based on length with space as a delimiter.
For example,
MY_STRING="welcome to programming world"
My output should be
STRING1="welcome to "
STRING2="programming "
The strings should be a maximum of 13 characters in length. The words after position 26 can be ignored.
You don't mention what version of Oracle you're using. If you're using 10g or above you can use regular expressions to get what you need:
with spaces as (
select regexp_instr('welcome to programming world' || ' '
, '[[:space:]]', 1, level) as s
from dual
connect by level <= regexp_count('welcome to programming world' || ' '
, '[[:space:]]')
)
, actual as (
select max(case when s <= 13 then s else 0 end) as a
, max(case when s <= 26 then s else 0 end) as b
from spaces
)
select substr('welcome to programming world',1,a)
, substr('welcome to programming world',a, b - a)
from actual
This finds the positional index of all the spaces, then finds the one that's nearest but less than 14. Lastly uses a simple substr to split your string. The strings will have a trailing space so you might want to trim this.
You have to concatenate your string with a space to ensure that there is a trailing space so the last word doesn't get removed if your string is shorter than 26 characters.
Assuming you're using an earlier version you could hack something together with instr and length but it won't be very pretty at all.