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.
Related
I have some codes and I want to replace a peace of that code only. in my case BB to XX
AA/BB
AA/BB1
AA/BB-1
BB
BB1
BB-1
I tried use to regexp_replace with this simple form
Query:
select regexp_replace('AA/BB','BB','XX') from dual;
Result:
AA/XX
Query:
select regexp_replace('AA/BB-1','BB','XX') from dual;
Result:
AA/XX-1
It works fine but it can happen that before the slash AA will be BB as well but this time it shouldn't be replaced but still works for the rest of codes.
select regexp_replace('BB/BB','BB','XX') from dual;
gives me XX/XX of course but I want to achieve BB/XX etc.
Alternatively - see comments within code, where "starting at position" reads as: if there are more than 1 BB substrings there, start at position of the 2nd BB within the MYVAL. Otherwise, start from the beginning of MYVAL.
Thank you, #GMB, for sample data.
SQL> with t as (
2 select 'AA/BB' myval from dual
3 union all select 'AA/BB1' from dual
4 union all select 'AA/BB-1' from dual
5 union all select 'BB' from dual
6 union all select 'BB' from dual
7 union all select 'BB1' from dual
8 union all select 'BB-1' from dual
9 union all select 'BB/BB' from dual
10 union all select 'AA/BB/BB-2' from dual
11 )
12 select myval,
13 regexp_replace
14 (myval, --> in MYVAL
15 'BB', --> replace BB
16 'XX', --> with XX
17 case when regexp_count(myval, 'BB') = 1 then 1 --> starting at position*
18 else instr(myval, 'BB', 1, 2)
19 end
20 ) result
21 from t;
MYVAL RESULT
---------- ---------------
AA/BB AA/XX
AA/BB1 AA/XX1
AA/BB-1 AA/XX-1
BB XX
BB XX
BB1 XX1
BB-1 XX-1
BB/BB BB/XX
AA/BB/BB-2 AA/BB/XX-2
9 rows selected.
SQL>
Maybe we could phrase this as: replace 'BB' that is not followed by '/'?
regexp_replace(myval, 'BB($|[^/])', 'XX\1')
Demo on DB Fiddle:
with t as (
select 'AA/BB' myval from dual
union all select 'AA/BB1' from dual
union all select 'AA/BB-1' from dual
union all select 'BB' from dual
union all select 'BB' from dual
union all select 'BB1' from dual
union all select 'BB-1' from dual
union all select 'BB/BB' from dual
)
select myval, regexp_replace(myval, 'BB($|[^/])', 'XX\1') newval from t
MYVAL | NEWVAL
:------ | :------
AA/BB | AA/XX
AA/BB1 | AA/XX1
AA/BB-1 | AA/XX-1
BB | XX
BB | XX
BB1 | XX1
BB-1 | XX-1
BB/BB | BB/XX
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>
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>
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.
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;