Insert characters between a string in Oracle SQL - oracle

I have data like this:
RowA
21788
2278
278
241740
I want the SQL output to be
RowA
2hr17min
22min
2min
24hr17min
I tried with below query but I can't get proper mins.
substr(to_CHAR(ROWA), 1, length(ROWA) - 4) || 'Hrs' ||
substr(to_CHAR(ROWA), 2, length(ROWA) - 3) || 'Mins'
Format is like HHMMSS

You can use simple string functions:
SELECT CASE
WHEN LENGTH(rowa) > 4
THEN SUBSTR(rowa, 1, LENGTH(rowa) - 4) || 'hr'
END
|| CASE
WHEN LENGTH(rowa) >= 4
THEN SUBSTR(rowa, -4, 2) || 'min'
WHEN LENGTH(rowa) > 2
THEN SUBSTR(rowa, 1, LENGTH(rowa) - 2) || 'min'
END AS duration
FROM my_tests;
Which, for the sample data:
CREATE TABLE my_tests ( RowA ) AS
SELECT '21788' FROM DUAL UNION ALL
SELECT '2278' FROM DUAL UNION ALL
SELECT '278' FROM DUAL UNION ALL
SELECT '241740' FROM DUAL;
Outputs:
DURATION
2hr17min
22min
2min
24hr17min
fiddle

Related

How to achieve one to many relation ship data as coma separated in below format

I have 2 tables and it is one to many relationship (parent & chdild). Its a dynamic table ,not a fixed data. More data can come in table.
user
Aid userName
1 author1
2 author2
3 author3
4 author4
etc
books
bid NAME Aid
1 x 1
2 y 1
3 z 2
4 z1 3
The Expected output is like below
'author1' AS author1,'x' AS x,'y' AS y,'author2' AS author2,'z' AS z,'author3' AS author3,'z1' AS z1
I have tried with parent table but how to get all row like in above format.
select listagg('''' || UserName || ''' as "' || UserName || '"', ',') within group (order by Aid)
from (select distinct Aid,UserName from user order by Aid);
Firstly, don't do this. If you want to pivot the data, do it in the third-party application (Java, C#, PHP, etc.) that you are using to access the database because that will support pivoting a data set rather than trying to force it through some dynamic SQL and trying to get a query to do something it is not intended to do.
However, if you really must (don't) then:
SELECT LISTAGG('''' || name || ''' AS ' || name, ',')
WITHIN GROUP (ORDER BY name) AS names
FROM (
SELECT username AS name
FROM "USER"
UNION
SELECT name
FROM books
)
Which, for the sample data:
CREATE TABLE "USER" (Aid, userName) AS
SELECT 1, 'author1' FROM DUAL UNION ALL
SELECT 2, 'author2' FROM DUAL UNION ALL
SELECT 3, 'author3' FROM DUAL UNION ALL
SELECT 4, 'author4' FROM DUAL;
CREATE TABLE books (bid, NAME, Aid) AS
SELECT 1, 'x', 1 FROM DUAL UNION ALL
SELECT 2, 'y', 1 FROM DUAL UNION ALL
SELECT 3, 'z', 2 FROM DUAL UNION ALL
SELECT 4, 'z1', 3 FROM DUAL;
Outputs:
NAMES
'author1' AS author1,'author2' AS author2,'author3' AS author3,'author4' AS author4,'x' AS x,'y' AS y,'z' AS z,'z1' AS z1
fiddle

Converting number to string and adding a character in Oracle

I am trying to add a character onto the end of a string using
CASE
WHEN PackageNum = 2 THEN to_char(DespatchNum + 'B')
WHEN PackageNum = 3 THEN to_char(DespatchNum + 'C')
WHEN PackageNum = 4 THEN to_char(DespatchNum + 'D')
WHEN PackageNum = 5 THEN to_char(DespatchNum + 'E')
ELSE to_char(DespatchNum)
END as ShipmentReference,
However I am getting the error
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
DespatchNum is a number
As an example, output would look like 1234B
Help appreciated.
You can use:
SELECT packagenum,
despatchnum,
CASE PackageNum
WHEN 2 THEN DespatchNum || 'B'
WHEN 3 THEN DespatchNum || 'C'
WHEN 4 THEN DespatchNum || 'D'
WHEN 5 THEN DespatchNum || 'E'
ELSE TO_CHAR(DespatchNum)
END as ShipmentReference
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name ( packagenum, despatchnum ) AS
SELECT LEVEL, 1234 FROM DUAL CONNECT BY LEVEL <= 6;
Outputs:
PACKAGENUM
DESPATCHNUM
SHIPMENTREFERENCE
1
1234
1234
2
1234
1234B
3
1234
1234C
4
1234
1234D
5
1234
1234E
6
1234
1234
db<>fiddle here
As mentioned by #gsalem in the comments, the concatenation was incorrect and to concatonate characters onto a string you have use || not +
You can also factor out TO_CHAR(DESPATCHNUM), since it's common to all cases.
Something like this:
with
tbl (packagenum, despatchnum) as (
select 2, 3002 from dual union all
select 5, 4122 from dual union all
select 7, 8320 from dual
)
select packagenum, despatchnum,
to_char(despatchnum) ||
case packagenum when 2 then 'B'
when 3 then 'C'
when 4 then 'D'
when 5 then 'E' end as shipmentreference
from tbl
;
PACKAGENUM DESPATCHNUM SHIPMENTREFERENCE
---------- ----------- -----------------
2 3002 3002B
5 4122 4122E
7 8320 8320

Oracle - Performance between Regexp_substr and Instr

As my title, somecases I see Regexp_substr faster and less cost than Instr and somecases its opposite.
I don't know when I should use Instr or Regexp_substr, someone can explain for me and tell me benefit of each? The example following:
**Regexp_substr:**
SELECT * FROM tabl1
WHERE 1 = 1
AND col1 IN (
SELECT regexp_substr(abc,'[^,]+',1,level) AS A
FROM (
SELECT 001 abc -- replace with parameter
FROM DUAL
)
CONNECT BY LEVEL <= LENGTH (REGEXP_REPLACE (abc,'[^,]'))+1 );
**Instr:**
SELECT * FROM tabl1
WHERE 1 = 1
AND INSTR (',' || '001' || ',',',' || col1 || ',') > 0 ;
Thanks!

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

Oracle/Hibernate Like: Finding String that only contain a single ';'

I'm trying to find all the records that contains only a single ; in a column.
For example
a;sdasd
as;dasd;dasd
as;dasd;das
only a;sdasd will be returned.
I have tried %;% but it will return all the strings that contain ;.
SELECT id
FROM your_table
WHERE LENGTH(col) - LENGTH(REPLACE(col,';')) = 1;
Is one solution.
Another uses REGEXP_LIKE:
WITH q AS (SELECT 1 ID, 'a;b;c;' str FROM dual
UNION
SELECT 2, ';abc' FROM dual
UNION
SELECT 3, 'a;b;c;defg;h' FROM dual
UNION
SELECT 4, 'abcdefghi;' FROM dual
UNION
SELECT 5, 'ab;cde' FROM dual
UNION
SELECT 6, 'abcdef' FROM dual)
SELECT *
FROM q
WHERE regexp_like(str,'^[^;]*;[^;]*$');
ID STR
---------- ------------
2 ;abc
4 abcdefghi;
5 ab;cde
Ine other possibility (no String manipulation is necessary):
FROM your_table
WHERE col like '%;%' AND INSTR(col, ';', 1) = INSTR(col, ';', -1)

Resources