Getting data from a column only if it contains number or special characters in Oracle - oracle

I want data from a column only if it contains special characters or numbers.
My query looks as follows:
Select First_name from account where regexp_like(First_name,'[0-9]')
But I don't know how to achieve that special character thing

Well you're most of the way there already, just add the special characters you are interested in to the character class you've already defined in the regexp:
Select First_name
from account
where regexp_like(First_name,'[0-9##$_!?*]')
To also select records where First_name is null use one of the two following queries:
Select First_name
from account
where regexp_like(First_name,'[0-9##$_!?*]')
or First_name is null
or
Select First_name
from account
where regexp_like(nvl(First_name,'!'),'[0-9##$_!?*]')
The first one explicitly selects rows where First_name is null while the second query gets it by substituting a special character string for null strings.

How about upside-down approach? Select values that aren't all letters. How? Remove them from the string! Something like this:
SQL> with account (id, first_name) as
2 (select 1, 'Little' from dual union all -- valid
3 select 2, 'der Leyen' from dual union all -- valid
4 select 3, 'F00t' from dual union all -- invalid; two zeros
5 select 4, 'Sco#tt' from dual union all -- invalid; #
6 select 5, 'Me#SO' from dual union all -- invalid; #
7 select 6, 'What_is_it' from dual union all -- invalid; _
8 select 7, '12.345' from dual union all -- invalid; digits
9 select 8, 'Huh? Whoa!' from dual -- invalid; ?!
10 )
11 select id,
12 first_name,
13 regexp_replace(first_name, '[[:alpha:] ]', null) repl
14 from account
15 where regexp_replace(first_name, '[[:alpha:] ]', null) is not null
16 order by id;
ID FIRST_NAME REPL
---------- ---------- ----------
3 F00t 00
4 Sco#tt #
5 Me#SO #
6 What_is_it __
7 12.345 12.345
8 Huh? Whoa! ?!
6 rows selected.
SQL>
Column REPL is here to show what's left after replacing letters (and a space) with null; you wouldn't normally display it.

Related

Specific Pattern Matching in Oracle

I have a close to 1000 records which have first two characters as alphabets and then an number of characters.
eg.
- BE123
- QT12124
- ST1000
- XY12345
and similar data....
I have a table X in Oracle having a column 'Serial Number' which will be having similar data , but it is of standard length 7 and also start with first two characters as alphabets.
I want to do a pattern matching on the column Serial Number where i can use LIKE and '%' matching on the characters after first two characters in the column for eg
if the column has a data
- BE00123 , it should start give me BE123 as matched data
- QT12124 , it is matched data
- ST11001 , unmatched data
- XY12345, matched data
Well, this returns what you asked. See if it helps.
SQL> with t_one (col) as
2 (select 'BE123' from dual union all
3 select 'QT12124' from dual union all
4 select 'ST1000' from dual union all
5 select 'XY12345' from dual
6 ),
7 t_two (col) as
8 (select 'BE00123' from dual union all
9 select 'QT12124' from dual union all
10 select 'ST11001' from dual union all
11 select 'XY12345' from dual
12 )
13 select o.col
14 from t_one o join t_two t on substr(o.col, 1, 2) = substr(t.col, 1, 2)
15 and instr(t.col, substr(o.col, 3)) > 0;
COL
-------
BE123
QT12124
XY12345
SQL>
Line 14: match first two characters
Line 15: check whether characters from T_ONE table, starting from position 3, are contained in the T_TWO table's column value

Oracle Rest Data Service Order by desc nulls last not working

I am not able order by field_name DESC with null last option. Since the default behaviour on DESC is nulls first, I would like them to be pushed at last.
"$orderby": {"ENAME":"DESC NULLS LAST"}
Thanks in advance
How about such a trick? If ENAME is NULL, use CHR(ASCII(1E4)) - something that is, hopefully, far enough to avoid valid first characters in actual names in your database.
SQL> with test (id, ename) as
2 (select 1, 'Little' from dual union
3 select 2, null from dual union
4 select 3, 'Zoot' from dual
5 )
6 select *
7 from test
8 order by decode(ename, null, chr(ascii(1E4)), ename) desc;
ID ENAME
---------- ------
2
3 Zoot
1 Little
SQL>

Oracle SQL Merge Multiple rows With Same ID But Out of Order Identifiers

I am trying to create a distinct list of parts to do analysis on in a table. The table contains a column of Part IDs and a column of Identifiers. The Identifiers are separated within the same entry by pipes but unfortunately the Identifiers are out of order. I'm not sure if this is possible but any help would be greatly appreciated!
For example (currently Both ID and Identifiers are VARCHAR2)
ID Identifiers
1 |1|2|
1 |2|1|
2 |3|A|1|B|
2 |B|1|3|A|
3 |1|3|2|
3 |1|5|
3 |2|1|3|
4 |AA|BB|1|3A|
4 |1|3A|AA|BB|
and I need the query to return
ID Identifiers
1 |1|2|
2 |3|A|1|B|
3 |1|5|
3 |1|3|2|
4 |1|AA|BB|3A|
It does not matter what specific order the identifiers are ordered in as long as all contents within that identifier are the same. For example, |1|5| or |5|1| doesn't matter but I need to see both entries |1|5| and |1|3|2. My original thought was to create separate out the identifiers into separate columns and then alphabetically concatenate back into one column but i'm not sure...thanks in advance!
Something like this (assuming there are no duplicate rows in the input table - if there are, the solution needs to be modified a bit).
In the solution I build the test_table for testing (it is not part of the solution), and I build another factored subquery in the WITH clause. This works in Oracle 11 and above. For earlier versions of Oracle, the subquery defined as prep needs to be moved as a subquery within the final query instead.
with
test_table ( id, identifiers ) as (
select '1', '|1|2|' from dual union all
select '1', '|2|1|' from dual union all
select '2', '|3|A|1|B|' from dual union all
select '2', '|B|1|3|A|' from dual union all
select '3', '|1|3|2|' from dual union all
select '3', '|1|5|' from dual union all
select '3', '|2|1|3|' from dual union all
select '4', '|AA|BB|1|3A|' from dual union all
select '4', '|1|3A|AA|BB|' from dual
),
prep ( id, identifiers, token ) as (
select id, identifiers, regexp_substr(identifiers, '[^|]+', 1, level)
from test_table
connect by level <= regexp_count(identifiers, '\|') - 1
and prior identifiers = identifiers
and prior sys_guid() is not null
)
select distinct id,
'|' || listagg(token, '|') within group (order by token) || '|'
as identifiers
from prep
group by id, identifiers
order by id, identifiers -- ORDER BY is optional
;
Output:
ID IDENTIFIERS
--- --------------------
1 |1|2|
2 |1|3|A|B|
3 |1|2|3|
3 |1|5|
4 |1|3A|AA|BB|
5 rows selected.

Oracle- Multiple rows in single row with adding column of duplicate value

Id Field_id Field_value
------------------------------
1 10 'A'
1 11 'B'
1 12 'C'
I want to make rows like
Id Field_id Field_value data_1 data_2
--------------------------------------
1 10 'A' 'B' 'C'
Pl help.
Take a look at this:
with t (Id, Field_id, Field_value) as (
select 1, 10, 'A' from dual union all
select 1, 11, 'B' from dual union all
select 1, 12, 'C' from dual
)
select FIELD_ID1, "10_FIELD_ID", "11_FIELD_ID","12_FIELD_ID"
from (select id, field_id, min(field_id) over() field_id1, field_value from t)
pivot (
max(field_value) field_id
for field_id in (10, 11, 12)
)
FIELD_ID1 10_FIELD_ID 11_FIELD_ID 12_FIELD_ID
---------------------------------------------------
10 A B C
Read more about pivot here
Normally, people look for PIVOT query, however, your input data is not at all duplicate as already mentioned in comments.
What you could do is, using subquery factoring, select id, 10 as field_id, field_value, thus making field_it static value as 10. Then use LISTAGG. But, the grouped rows would be a single column as delimeter seperated values.
I hope your requirement is exactly what you stated and not a typo or a mistake while posting.

remove a varchar2 string from the middle of table data values

Data in the file_name field of the generation table should be an assigned number, then _01, _02, or _03, etc. and then .pdf (example 82617_01.pdf).
Somewhere, the program is putting a state name and sometimes a date/time stamp, between the assigned number and the 01, 02, etc. (82617_ALABAMA_01.pdf or 19998_MAINE_07-31-2010_11-05-59_AM.pdf or 5485325_OREGON_01.pdf for example).
We would like to develop a SQL statement to find the bad file names and fix them. In theory it seems rather simple to find file names that include a varchar2 data type and remove it, but putting the statement together is beyond me.
Any help or suggestions appreciated.
Something like:
UPDATE GENERATION
SET FILE_NAME (?)
WHERE FILE_NAME (?...LIKE '%STRING%');?
You can find the problem rows like this:
select *
from Files
where length(FILE_NAME) - length(replace(FILE_NAME, '_', '')) > 1
You can fix them like this:
update Files
set FILE_NAME = SUBSTR(FILE_NAME, 1, instr(FILE_NAME, '_') -1) ||
SUBSTR(FILE_NAME, instr(FILE_NAME, '_', 1, 2))
where length(FILE_NAME) - length(replace(FILE_NAME, '_', '')) > 1
SQL Fiddle Example
You can also use Regexp_replace function:
SQL> with t1(col) as(
2 select '82617_mm_01.pdf' from dual union all
3 select '456546_khkjh_89kjh_67_01.pdf' from dual union all
4 select '19998_MAINE_07-31-2010_11-05-59_AM.pdf' from dual union all
5 select '5485325_OREGON_01.pdf' from dual
6 )
7 select col
8 , regexp_replace(col, '^([0-9]+)_(.*)_(\d{2}\.pdf)$', '\1_\3') res
9 from t1;
COL RES
-------------------------------------- -----------------------------------------
82617_mm_01.pdf 82617_01.pdf
456546_khkjh_89kjh_67_01.pdf 456546_01.pdf
19998_MAINE_07-31-2010_11-05-59_AM.pdf 19998_MAINE_07-31-2010_11-05-59_AM.pdf
5485325_OREGON_01.pdf 5485325_01.pdf
To display good or bad data regexp_like function will come in handy:
SQL> with t1(col) as(
2 select '826170_01.pdf' from dual union all
3 select '456546_01.pdf' from dual union all
4 select '19998_MAINE_07-31-2010_11-05-59_AM.pdf' from dual union all
5 select '5485325_OREGON_01.pdf' from dual
6 )
7 select col bad_data
8 from t1
9 where not regexp_like(col, '^[0-9]+_\d{2}\.pdf$');
BAD_DATA
--------------------------------------
19998_MAINE_07-31-2010_11-05-59_AM.pdf
5485325_OREGON_01.pdf
SQL> with t1(col) as(
2 select '826170_01.pdf' from dual union all
3 select '456546_01.pdf' from dual union all
4 select '19998_MAINE_07-31-2010_11-05-59_AM.pdf' from dual union all
5 select '5485325_OREGON_01.pdf' from dual
6 )
7 select col good_data
8 from t1
9 where regexp_like(col, '^[0-9]+_\d{2}\.pdf$');
GOOD_DATA
--------------------------------------
826170_01.pdf
456546_01.pdf
To that end your update statement might look like this:
update your_table
set col = regexp_replace(col, '^([0-9]+)_(.*)_(\d{2}\.pdf)$', '\1_\3');
--where clause if needed

Resources