Oracle get all matched occurrences from one column with REGEXP - sql

Been using this query but I don't get what I want, anyone can help, please? I want to consolidate all the matched multiple occurrences and display the records in the table.
SELECT REGEXP_SUBSTR(STR,'^C-.+|^WHT.+',1, LEVEL,1,'m') AS CHARGE_NUMBER
FROM
(
SELECT DBMS_LOB.SUBSTR(COL_DATA, 2000,1) AS STR, TRANX_DATE, USER_ID
FROM TABLE_1
)
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(STR,'^C-.+|^WHT.+',1,1,'m'))+1
Data in one Column
A-DATE|27SEP2021|TRANSACTION_NUMBER|0001|USERID|1000
B-THE|QUICK|BROWN|123467899|OVER|THE|1234567899|DOG
C-50000000001
WHT639281234567
B-THE|123456789|BROWN|FOX|OVER|THE|LAZY|DOG
C-50000000002
WHT639281234568
B-THE|1234567899|BROWN|123457899|OVER|THE|LAZY|DOG
C-50000000003
B-THE|QUICK|BROWN|1234567899|OVER|1234567899|LAZY|DOG
WHT639281234569
B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
C-50000000004
WHT639281234570
B-THE|1234567899|BROWN|123467899|OVER|THE|1234567899|DOG
DESIRED RESULT:
CHARGE_NUMBER
50000000001
639281234567
50000000002
639281234568
50000000003
639281234569
50000000004
639281234570

Here's one option: select values you need (using regex), then remove superfluous characters (C- and WHT), looping through the string as many times as there are WHTs times 2 (because you have C- and WHTs to look for).
SQL> with test (col) as
2 (select 'A-DATE|27SEP2021|TRANSACTION_NUMBER|0001|USERID|1000
3 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
4 C-50000000001
5 WHT639281234567
6 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
7 C-50000000002
8 WHT639281234568
9 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
10 C-50000000003
11 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
12 WHT639281234569
13 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG
14 C-50000000004
15 WHT639281234570
16 B-THE|QUICK|BROWN|FOX|OVER|THE|LAZY|DOG' from dual
17 )
18 select replace(replace(regexp_substr(col, 'C-\d+|WHT\d+', 1, level), 'C-', ''), 'WHT', '') charge_number
19 from test
20 connect by level <= regexp_count(col, 'WHT') * 2;
CHARGE_NUMBER
--------------------------------------------------------------------------------
50000000001
639281234567
50000000002
639281234568
50000000003
639281234569
50000000004
639281234570
8 rows selected.
SQL>

Related

Trying to select 5 random rows from table as part of testing [duplicate]

This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
How to get records randomly from the oracle database?
(9 answers)
Closed 4 months ago.
as part of some testing I am attempting to select 5 random rows from a table, the code I'm running is:
select *
from Table_Name
order by RAND()
Limit 5;
Upon executing the code I am presented with the error SQL command not properly ended, could someone advise on how to get this working? for reference I am using oracle SQL Developer.
Thanks in advance
With sample data like this:
ID
NAME_ID
1
NAME_FOR_1
2
NAME_FOR_2
3
NAME_FOR_3
4
NAME_FOR_4
5
NAME_FOR_5
6
NAME_FOR_6
7
NAME_FOR_7
8
NAME_FOR_8
9
NAME_FOR_9
10
NAME_FOR_10
11
NAME_FOR_11
12
NAME_FOR_12
13
NAME_FOR_13
14
NAME_FOR_14
15
NAME_FOR_15
You can do it with a nested query:
SELECT
ID, NAME_ID
FROM
(
SELECT
ID, NAME_ID
FROM
a_table
ORDER BY DBMS_RANDOM.RANDOM
)
WHERE ROWNUM <= 5;
... the result will be different every time you run the query...
/* Result (one of)
ID NAME_ID
---------- -------------------------------------------------
14 NAME_FOR_14
9 NAME_FOR_9
13 NAME_FOR_13
15 NAME_FOR_15
8 NAME_FOR_8
*/
Regards...

Oracle Insert Value Into Middle of Existing Value

This is similar to my previous question. I have the following partial docket numbers:
docket_number
-------------
2012JV592
2016DR138
2018JV84
If the docket number is less than 10 digits, then I need to insert 0's after the second letter until the lenth is 10 digits. Updated docket numbers would look like this.
docket_number
-------------
2012JV0592
2016DR0138
2018JV0084
One option might be to
split docket_number into two parts: first part contains digits and letters, the second contains the trailing number
result is concatenation of the first part and the second part left padded with zeroes up to total length of 10 characters
SQL> with test (docket_number) as
2 (select '2012JV592' from dual union all
3 select '2016DR138' from dual union all
4 select '2018JV84' from dual
5 ),
6 temp as
7 (select docket_number,
8 regexp_substr(docket_number, '[[:digit:]]+[[:alpha:]]+') part1,
9 regexp_substr(docket_number, '[[:digit:]]+$') part2
10 from test
11 )
12 select case when length(docket_number) < 10 then
13 part1 || lpad(part2, 10 - length(part1), '0')
14 else docket_number
15 end result
16 from temp;
RESULT
--------------------------------------------------------------------------------
2012JV0592
2016DR0138
2018JV0084
SQL>
How to update rows in a table? By using such a SELECT in UPDATE, e.g.
SQL> select * from test;
DOCKET_NUM
----------
2012JV592
2016DR138
2018JV84
SQL> update test a set
2 a.docket_number =
3 (with temp as
4 (select b.docket_number,
5 regexp_substr(b.docket_number, '[[:digit:]]+[[:alpha:]]+') part1,
6 regexp_substr(b.docket_number, '[[:digit:]]+$') part2
7 from test b
8 )
9 select case when length(t.docket_number) < 10 then
10 t.part1 || lpad(t.part2, 10 - length(t.part1), '0')
11 else docket_number
12 end
13 from temp t
14 where t.docket_number = a.docket_number
15 );
3 rows updated.
SQL> select * from test;
DOCKET_NUM
----------
2012JV0592
2016DR0138
2018JV0084
SQL>
You can split the data into three parts as digit group1, letters group, and digit group2 by using regexp_substr() functions, and lpad() function in order to add zeroes just before the second digit group, and then concatenate them directly by using || operators, assuming that you have the same data model for the whole table,
UPDATE t
SET docket_number = regexp_substr(docket_number,'[[:digit:]]+')||
regexp_substr(docket_number,'[[:alpha:]]+')||
lpad('0',10-length(docket_number),'0')||
regexp_substr(docket_number,'[[:digit:]]+$')
Demo
Is it the case that your docket_number should always follow the format 4 digits (year?) followed by 2 letters followed by 4 digits. Then simple sub-string of the docket_number and subsequent re-concatenation is sufficient.
select docket_number
, substr(docket_number,1,6) || lpad(nvl(substr(docket_number,7),'0'),4,'0')
from test_dn
where length(docket_number) < 10
order by docket_number;
and for update:
update test_dn
set docket_number = substr(docket_number,1,6) || lpad(nvl(substr(docket_number,7),'0'),4,'0')
where length(docket_number) < 10;
If the format holds true then, depending on table size, this could be significantly faster as regular expressions are relative slow.

MS access Group by

I have a big access database table and part of it is given below and I want to get the minimum value by group, which is the minimum value for 3, 5, 9,.... I have tried in the query using minimum value of Group by but it couldn't give me:
I want like:
Point ParaA Modvalue MinofParaA
3 0.02345610000 1.1304602327522
5 0.541734307717087 0.592591581187
7 4.4094560894325 0.393245327246
9 5.5450476528689 1.034165859885
11 ….. …….
13 ……. …….
Part of my database is:
Point ParaA Modvalue
3 1.01537282042687E-07 1.1304602327522
3 5.41734307717087E-06 1.592591581187
3 4.4094560894325E-05 2.393245327246
3 5.5450476528689E-05 1.034165859885
3 5.6210847721211E-05 1.9269298608176
3 7.33007048018759E-05 3.17251848741499
3 1.26935918181651E-04 7.577150615919
3 1.27908837646644E-04 4.466340029852
9 0.205576008517929 32.1580666011739
9 0.2058403012141 6.080246238675
9 0.205888794863275 4.48451872092713
9 0.205970780609684 30.2695831828562
9 0.206476048361761 2.3287221969481
9 0.206500794273712 4.48657381393526
9 0.206507173199086 3.54388543810806
9 0.206701769548586 77.5713240109687
5 0.127510144904596 0.692657575677875
5 0.127593565284236 16.812067790848
5 0.127765437607527 1.5228257707606
5 0.12803789311445 13.185719005611
5 0.12821555669427 15.488318488284
5 0.128929582513692 1.24166466944275
5 0.129137495154857 20.811097854043
5 0.129492706221109 1.73300570963531
5 0.130290993399936 6.7783307471853
5 0.130328615583637 11.879218642047
I have tried like: Group by and min (minimum value) but it doesn't give me what I want.
Based on the information provided in the comments, perhaps something along the following lines yields the result that you require:
select t.point, first(t.paraA), min(t.minofpara)
from YourTable t
group by t.point
The second column of this query essentially returns the value of a 'random' record within each point group. Change YourTable to the name of your table.
EDIT: Based on your comments to my answer, it seems that you simply require:
select t.point, min(t.paraa)
from YourTable t
group by t.point
To select the record(s) which hold this minimum, you might then use:
select t1.* from YourTable t1 inner join
(
select t2.point, min(t2.paraa) as mp
from YourTable t2
group by t2.point
) t3
on t1.point = t3.point and t1.paraa = t3.mp

SQL Inserting in loop using value (sysguid) multiple times

I currently have the following script for inserting some dummy data into one of my tables for testing purposes.
I can call it and pass the number of entries I would like to have. That's working well.
Now the problem is that some of the data is not working.
The CRecordID should have in all three lines (12, 17, 19) the same value.
Is there a way to archive this?
WHENEVER SQLERROR EXIT
PROMPT inserting
INSERT INTO MySchema.MyTable (MYRECORD, TMSTAMP, SHORTRECORD, CRecordID) (
SELECT
'<MYRECORD>
<TimeStamp>'||TO_CHAR(SYSDATE,'DD.MM.YY')||' '||to_char(to_date('2000-01-01', 'yyyy-mm-dd')+dbms_random.value(1,1000), 'HH24:MI:SS')||'</TimeStamp>
<User>Test_User_1</User>
<Application>Application1</Application>
<Action>Dummy action text</Action>
<INFO>dummy info text</INFO>
<CRecordID>'||'CID_'||sys_guid()||'</CRecordID> -- line 12
</MYRECORD>',
to_date(SYSDATE,'DD.MM.YY'),
'<SHORTRECORD>
<User>Test_User_1</User>
<CRecordID>'||'CID_'||sys_guid()||'</CRecordID> -- line 17
</SHORTRECORD>',
'CID_'||sys_guid() -- line 19
FROM DUAL connect by level <= &1
);
COMMIT;
PROMPT inserting done
Note: The Database is an Oracle DB.
Select SYS_GUID() separately (using a CTE, for example, as in my example) and concatenate its value with your columns (I used L12 and L17 to indicate lines 12 and 17 you mentioned).
SQL> with gujda as
2 (select sys_guid() guj
3 from dual
4 connect by level <= 4
5 )
6 select 'L12_' || g.guj l12,
7 'L17_' || g.guj l17
8 from gujda g;
L12 L17
------------------------------------ ------------------------------------
L12_EFB5A4947D2E4B7BBE6017E57C673ABF L17_EFB5A4947D2E4B7BBE6017E57C673ABF
L12_3E2D5B50D7C44C7FA6073A9F739687CF L17_3E2D5B50D7C44C7FA6073A9F739687CF
L12_724C21F7914B423B8CBDDC6A44AD2016 L17_724C21F7914B423B8CBDDC6A44AD2016
L12_F15D6C9865424E5C8FFFEA9C09DD6D37 L17_F15D6C9865424E5C8FFFEA9C09DD6D37
SQL>

FETCH DATA BASED ON PARTICULAR STRING

I need to fetch records based on particular type(FFRT-TR= ) and then replace it. For example below are the record types
20017546 FFRT-TR= 3456
TT:SX 2398 FFRT-TR=6532
I need to fetch records which contains FFRT-TR= and then replace the whole the of FFRT-TR=3456 Required Output based on the above examples: 20017546(for 1st example) 2398(for 2nd example)
Please help. Thanks in advance
Something like this? Oracle-ish (you didn't specify the database you use), but - hopefully - you'll be able to rewrite it if necessary.
SQL> with test (col) as
2 (select '20017546 FFRT-TR= 3456' from dual union
3 select 'TT:SX 2398 FFRT-TR=6532' from dual
4 )
5 select
6 col,
7 replace(regexp_substr(col, '\d+ FFRT-TR='), 'FFRT-TR=', '') result
8 from test;
COL RESULT
----------------------- ----------------------------------------------------
20017546 FFRT-TR= 3456 20017546
TT:SX 2398 FFRT-TR=6532 2398
SQL>