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.
Related
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>
Example
Value entered by the user :34,26 (a+)
Values in the table:
34,14........A+
34,42........A++
34,52........A++
.
.
.
The value entered by the user is between a+ and a++. In order to find the value of user, take the average of the closest upper and closest lower value, rounding up to the upper value if the value entered by the user is greater than the average, if the value entered by the user is lower than the average. Can you help with the sql query that will round to the lower value?
There are probably many ways to do that; as far as I understood, you want to find value (stored in the table) which is the closest to value you enter as a "parameter". If that's so, Oracle-based example (you originally tagged the question as such).
With sample data:
SQL> set ver off
SQL> select * from test;
COL
----------
34,14
34,42
34,52
Query:
SQL> with
2 minimax as
3 -- find values in the TEST table that represent boundaries around entered value
4 (select (select max(t.col) from test t where &&val >= t.col) mincol,
5 (select min(t.col) from test t where &&val <= t.col) maxcol,
6 (select max(t.col) from test t) maxx,
7 (select min(t.col) from test t) minn,
8 v.val
9 from dual v
10 )
11 -- return the closest boundary
12 select
13 case when mincol is null then minn
14 when maxcol is null then maxx
15 when abs(&&val - mincol) < abs(&&val - maxcol) then mincol
16 else maxcol
17 end as result
18 from minimax;
Enter value for val: 34.26
RESULT
----------
34,14
Some more testing:
SQL> undefine val
SQL> /
Enter value for val: 31
RESULT
----------
34,14
SQL> undefine val
SQL> /
Enter value for val: 36
RESULT
----------
34,52
SQL> undefine val
SQL> /
Enter value for val: 34.42
RESULT
----------
34,42
SQL>
Simple and quick question
If I have column have values in decimals
number
10.20
13.4000
15.987
i Want to remove the decimal from display the output without decimal
number
1020
134000
15987
I have tried
select replace(number, '.','') from table
I got the result but is there any other way to solve it.
Apparently, values you're dealing with are strings, aren't they? Otherwise, you wouldn't have all those trailing zeros.
Anyway, if it happens that these are numbers after all, a little bit of mathematics might produce the desired result. For example:
SQL> with test (num) as
2 (select 10.201 from dual union
3 select 13.4000 from dual union
4 select 15.987 from dual
5 )
6 select num,
7 num * power(10, to_number(length(to_char(num - trunc(num))) - 1)) result
8 from test;
NUM RESULT
---------- ----------
10,201 10201
13,4 134
15,987 15987
SQL>
I want to get a list ip addresses whose last 3 digits don't fall in the range 0 to 200. I tried using REGEXP_LIKE as below. But it is giving me wrong result.
select * from ip_data
where REGEXP_LIKE(substr(ip_address,instr(ip_address,'.',1,3)+1),'[^0-200]');
It seems to have matched each digits with 0-200 numbers individually.
I want to use only REGEXP_LIKE as I've to take the range from another table where it is stored in the format [0-200].
Any suggestions would be of great help.
Using REGEXP_SUBSTR:
SQL> WITH DATA AS(
2 SELECT '127.0.0.1' ip FROM dual UNION ALL
3 SELECT '127.0.0.201' ip FROM dual
4 )
5 SELECT * FROM DATA
6 WHERE REGEXP_SUBSTR(ip,'[[:digit:]]{1,3}',1, 4)
7 NOT BETWEEN 0 AND 200
8 /
IP
-----------
127.0.0.201
SQL>
Using simple SUBSTR:
SQL> WITH DATA AS(
2 SELECT '127.0.0.1' ip FROM dual UNION ALL
3 SELECT '127.0.0.201' ip FROM dual
4 )
5 SELECT * FROM DATA
6 WHERE to_number(substr(ip,instr(ip,'.',1,3)+1))
7 NOT BETWEEN 0 AND 200
8 /
IP
-----------
127.0.0.201
SQL>
I would go with the simple SUBSTR approach since it is less resource consuming, less CPU utilization, thus better performance.
You don't need regular expression for that:
to_number(substr(ip_address,instr(ip_address,'.',1,3)+1)) not between 0 and 200
Something like this should works:
select ip_address from ip_data
where NOT REGEXP_LIKE(ip_address,'\.(([0-9])|([1-9][0-9])|([1][0-9][0-9])|(200))$');
I am putting a bit of SQL into an Oracle script, if I run the Vanilla SQL i get the correct output of one single returned value/record. However in my custom function I get the value I am looking for returned as many times as there are records. Here is an example of what I have.
create function EXAMPLE_FUNCTION (passedID in NUMBER)
return NUMBER
IS
returnValue NUMBER;
BEGIN
SELECT "TABLE1"."ID" INTO returnValue
FROM "TABLE1" WHERE "TABLE1"."ID" = passedID;
RETURN returnValue;
END;
So if TABLE1 has 20 records I will get the record with ID 1 returned 20 times,
I am not sure where its going wrong, but I'm sure its simple!
You are probably calling the function like this:
select EXAMPLE_FUNCTION (1)
from my_table
Call it without the from:
select EXAMPLE_FUNCTION (1)
EDIT:
As pointed by Shannon Oracle requires the from clause so I searched and found examples using the dual table:
select EXAMPLE_FUNCTION (1)
from dual
Just do something like: SELECT EXAMPLE_FUNCTION(1) FROM dual;
Would something like the below work in your function?
Select COUNT(*) into returnValue
from TABLE1
where Table1.ID = passedID;
What value are you using for passedID? If you want to get soemthing different out for each row you need to pass something different in.
Compare these two function calls. First a fixed value:
SQL> select example_function(1) from table1
2 /
EXAMPLE_FUNCTION(1)
-------------------
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
20 rows selected.
SQL>
Then using the table column to supply the parameter:
SQL> select example_function(id) from table1
2 /
EXAMPLE_FUNCTION(ID)
--------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
20 rows selected.
SQL>