How to sort alphanumeric String in oracle? - sql

Input is:
Section1
Section2
Section3
Section10
Section11
Section1A
Section1B
Section12
Section11A
Section11B
And I want output like:
Section1
Section1A
Section1B
Section2
Section3
Section10
Section11
Section11A
Section11B
Section12
I tried query :
select section_name
from sections
order by length(section_name),section_name

Assuming that the structure of your strings is fixed, as in your example, this could be a way:
SQL> select x,
2 to_number(regexp_substr(x, '[0-9]+')) numericPart,
3 regexp_substr(x, '([0-9]+)([A-Z])', 1, 1, '', 2) optionalChar
4 from (
5 select 'Section1' x from dual union all
6 select 'Section2' from dual union all
7 select 'Section3' from dual union all
8 select 'Section10' from dual union all
9 select 'Section11' from dual union all
10 select 'Section1A' from dual union all
11 select 'Section1B' from dual union all
12 select 'Section12' from dual union all
13 select 'Section11A' from dual union all
14 select 'Section11B' from dual
15 )
16 order by numericPart,
17 optionalChar nulls first
18 ;
X NUMERICPART OPTIONALCHAR
---------- ----------- ----------------------------------------
Section1 1
Section1A 1 A
Section1B 1 B
Section2 2
Section3 3
Section10 10
Section11 11
Section11A 11 A
Section11B 11 B
Section12 12
Here you first order by the numeric part, treating it as number, and then consider the (optional) character after the number.

Related

ORACLE Sort Alphabetically Upper A, Lower a, numerics

I am sorting with Oracle version 12 with the following NLS parameters
NLS_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_COMP BINARY
Eg. " 1Andy"," Andy","Andy","andy","Aaron","Bob"
SELECT name from employee order by name
result:
" 1Andy"," Andy","Aaron","Andy","Bob","andy"
if I change the NLS_SORT to WEST_EUROPEAN, it is suppose to be " 1Andy"," Andy","Aaron","Andy","andy","Bob"
but the result is " 1Andy"," Andy","andy","Aaron","Andy","Bob"
where andy even though is lower case goes in the middle.
SELECT name from employee order by NLSSORT(name ,'NLS_SORT=WEST_EUROPEAN')
enter image description here
To begin with, you can have case-insensitive sorting by adding _ci the the collation spec: west_european_ci. That being said, it seems in west_european sorting spec, number come after alpha chars. Here's what I get with your data using different collation specs
SQL> with dt as (
2 select ' 1Andy' cv from dual
3 union all
4 select ' Andy' from dual
5 union all
6 select '1Andy' from dual
7 union all
8 select 'Andy' from dual
9 union all
10 select 'andy' from dual
11 union all
12 select 'Aaron' from dual
13 union all
14 select 'Bob' from dual)
15 select *
16 from dt
17 order by cv;
CV
------
1Andy
Andy
1Andy
Aaron
Andy
Bob
andy
7 rows selected.
SQL>
SQL> with dt as (
2 select ' 1Andy' cv from dual
3 union all
4 select ' Andy' from dual
5 union all
6 select '1Andy' from dual
7 union all
8 select 'Andy' from dual
9 union all
10 select 'andy' from dual
11 union all
12 select 'Aaron' from dual
13 union all
14 select 'Bob' from dual)
15 select *
16 from dt
17 order by nlssort(cv,'NLS_SORT=WEST_EUROPEAN');
CV
------
Andy
1Andy
Aaron
Andy
andy
Bob
1Andy
7 rows selected.
SQL>
SQL> with dt as (
2 select ' 1Andy' cv from dual
3 union all
4 select ' Andy' from dual
5 union all
6 select '1Andy' from dual
7 union all
8 select 'Andy' from dual
9 union all
10 select 'andy' from dual
11 union all
12 select 'Aaron' from dual
13 union all
14 select 'Bob' from dual)
15 select *
16 from dt
17 order by nlssort(cv,'NLS_SORT=WEST_EUROPEAN_ci');
CV
------
Andy
1Andy
Aaron
Andy
andy
Bob
1Andy
7 rows selected.

How to find a row where col have alphabets,numbers or special characters (except hyphen,apostrophe and space) in Oracle SQL

I have to find the name like : Robert#jr23 (There must be Alphabet,Any Special characters or Numbers except hyphen(-),apostrophe (') and Space).
I was doing as below:
select * from test where REGEXP_LIKE(trim(NAME_1), '[^- '']')
But I am not getting the right results with this.
Need to match:
Kevin#123
bob#jr
mike$dr
Needs to exclude:
Alex-jr
Robert'jr
Brian jr
You need to use not with a pattern matching the values you want to exclude. Otherwise you are matching strings that contain any character that is not in the exclusion list, which is all of them.
select column_value
from ora_mining_varchar2_nt
( 'Kevin#123'
, 'bob#jr'
, 'mike$dr'
, 'Alex-jr'
, 'Robert''jr'
, 'Brian jr'
, 'A!' )
where 1=1
and not regexp_like(column_value,'[- '']')
and regexp_like
(column_value, '([A-Z0-9]+[^A-Z0-9])|([^A-Z0-9]+[A-Z0-9])', 'i') ;
Edit: added a regex_like condition to ensure that values contain a letter or digit and a 'special character', meaning here a character that is neither a letter, digit or space, ' or -.
You can use following query to include all special characters except space, - and '
SQL> with tbl(name) as (
2 select 'Kevin#123' from dual union
3 select 'bob#jr' from dual union
4 select 'mike$dr' from dual union
5 select 'Alex-jr' from dual union
6 select 'Brian jr' from dual union
7 select 'Brian)jr' from dual union
8 select 'Robert''jr' from dual
9 )
10 select *
11 from tbl
12 where regexp_like(name, '[^[a-z]|[A-Z]|[:space:]|[:cntrl:]|/]')
13 and not regexp_like(name,'[- '']');
NAME
---------
Brian)jr -- see this is included
Kevin#123
bob#jr
mike$dr
SQL>
One option is to replace everything that's valid with NULL, and what remains is invalid:
SQL> with test (col) as
2 (select 'Robert#jr23' from dual union all
3 select 'Kevin#123' from dual union all
4 select 'bob#jr' from dual union all
5 select 'mike$dr' from dual union all
6 select 'Alex-jr' from dual union all
7 select 'Robert''jr' from dual union all
8 select 'Brian jr' from dual
9 )
10 select col
11 From test
12 where regexp_replace(col, '[[:alpha:]]|[[:digit:]]|-|''', null) is not null;
COL
-----------
Robert#jr23
Kevin#123
bob#jr
mike$dr
Brian jr
SQL>
I'm confused about what you, actually, want to get as a result. Here are some examples which show result of such a regular expression; which IDs do you want to get as a result?
SQL> with test (id, col) as
2 (select 1, 'Robert#jr23' from dual union all
3 select 2, 'Kevin#123' from dual union all
4 select 3, 'bob#jr' from dual union all
5 select 4, 'mike$dr' from dual union all
6 select 5, 'Alex-jr' from dual union all
7 select 6, 'Robert''jr' from dual union all
8 select 7, 'Brian jr' from dual union all
9 select 8, 'Brian10' from dual
10 )
11 select col,
12 regexp_replace(col,
13 '[[:alpha:]]|[[:digit:]]|[[:space:]]|-|''', null) result
14 from test;
COL RESULT
----------- ----------
Robert#jr23 #
Kevin#123 #
bob#jr #
mike$dr $
Alex-jr
Robert'jr
Brian jr
Brian10
8 rows selected.
SQL>
One of your comments says:
select a customer name where there must be a special character or numbers (except space, Hyphen and apostrophe)
which means that numbers and special characters should be treated as "equal". If that's so, does this help?
SQL> with test (id, col) as
2 (select 1, 'Robert#jr23' from dual union all
3 select 2, 'Kevin#123' from dual union all
4 select 3, 'bob#jr' from dual union all
5 select 4, 'mike$dr' from dual union all
6 select 5, 'Alex-jr' from dual union all
7 select 6, 'Robert''jr' from dual union all
8 select 7, 'Brian jr' from dual union all
9 select 8, 'Brian10' from dual
10 )
11 select id, col
12 from test
13 where regexp_replace(col, '[[:alpha:]]|[[:space:]]|-|''', '')
14 is not null;
ID COL
---------- -----------
1 Robert#jr23
2 Kevin#123
3 bob#jr
4 mike$dr
8 Brian10
SQL>

To find the starting and ending points in a sequence

I've a table (T1) with one column (C1) with the below values
1
2
3
5
6
8
9
10
I want the output to print the continuous sequences with start and ending points like below.
1-3
5-6
8-10
Could you please help?
Any Database is fine.
Oracle: sample data first, while code you really need begins at line #11.
SQL> with t1 (c1) as
2 (select 1 from dual union all
3 select 2 from dual union all
4 select 3 from dual union all
5 select 5 from dual union all
6 select 6 from dual union all
7 select 8 from dual union all
8 select 9 from dual union all
9 select 10 from dual
10 )
11 select min(c1), max(c1)
12 from (select c1, c1 - row_number() over (order by c1) rn
13 from t1
14 )
15 group by rn
16 order by rn;
MIN(C1) MAX(C1)
---------- ----------
1 3
5 6
8 10
SQL>
You can use the following query. I have tested it with SQL Server, but I think it will work without modifications in Oracle:
create table t1(c1 int);
insert into t1
select *
from (values(1),(2),(3),(5),(6),(8),(9),(10))t(x);
select case when count(*) >1 then
concat(min(c1),'-',max(c1))
else concat(max(c1),'')
end as concat_cs
from (
select c1
,ROW_NUMBER() over(order by c1 asc) as rnk
,c1 - ROW_NUMBER() over(order by c1 asc) as grp
from t1
)x
group by x.grp
Output
concat_cs
1-3
5-6
8-10
with stab as (
select 1 as val from dual union all
select 2 as val from dual union all
select 3 as val from dual union all
select 5 as val from dual union all
select 6 as val from dual union all
select 8 as val from dual union all
select 9 as val from dual union all
select 10 as val from dual union all
select 13 as val from dual union all
select 15 as val from dual union all
select 16 as val from dual union all
select 17 as val from dual union all
select 18 as val from dual union all
select 19 as val from dual union all
select 23 as val from dual
),sq2 as(
select
row_number() over(order by 1) as rownumber,val
from stab
)
select
a.val,b.val
from sq2 A
join sq2 b on b.rownumber = a.rownumber+2
where mod(A.rownumber,3)=1
Output:
1 3
5 8
9 13
15 17
18 23

Regular expression matching with Oracle

I am working on SQL Developer. I want only those records which have non-numeric data. The query I used is:
select * from TBL_NAME where regexp_like (mapping_name,'%[!0-9]%');
Strangely this is not working.
How about this? As you said, return values that are NOT numbers.
SQL> with test (col) as
2 (select 'abc123' from dual union
3 select '12345' from dual union
4 select 'abc' from dual union
5 select '($ff3' from dual union
6 select '12.345' from dual
7 )
8 select col
9 from test
10 where not regexp_like (col, '^\d+|(\.\d+)$');
COL
------
($ff3
abc
abc123
SQL>
If there are no decimal values, regular expression is even simpler: '^\d+$'
[EDIT, after sample data have been provided]
Piece of cake:
SQL> with test (col) as
2 (select 'ABC' from dual union
3 select 'BCE1' from dual union
4 select '2GHY' from dual union
5 select 'WE56S' from dual union
6 select 'TUY' from dual
7 )
8 select col
9 from test
10 where not regexp_like (col, '\d');
COL
-----
ABC
TUY
SQL>

Select values is a row as column values

How can I retrieve values in a row as column values?
Example:
Consider the output of below query as INPUT :
Select 1,2,3,4,5,6,7,8,9,10
from dual;
I need a query that can give below output:
COL1
----
1
2
3
4
5
6
7
8
9
10
SELECT 1 AS "COL1" FROM dual
UNION
SELECT 2 FROM dual
UNION
SELECT 3 FROM dual
UNION
SELECT 4 FROM dual
UNION
SELECT 5 FROM dual
UNION
SELECT 6 FROM dual
UNION
SELECT 7 FROM dual
UNION
SELECT 8 FROM dual
UNION
SELECT 9 FROM dual
UNION
SELECT 10 FROM dual ;
If you want to generate a sequence of numbers in Oracle:
with n as (
select level as n
from dual
connect by level <= 10
)
select *
from n;
Or, if you have 10 columns, you can do an unpivot. An easy way is with union all:
select col1 from t union all
select col2 from t union al
. . .
select col10 from t;