Need to get the max value in a given string after matching with a column - oracle

Consider this string '123456789' and the table consisting of col1 with the values as discribed below:
Col1
123
456
789
I need to write a query so the query will have to check for every value in the col1 and output the max matched with the string '123456789' in this i need to get output as 789.

Setup:
create table t (c varchar2(10));
insert into t values ('123');
insert into t values ('456');
insert into t values ('789');
commit;
Query:
select c, instr('123456789',c) as pos
from t
order by 2 desc
fetch first 1 row only;
Result:
C POS
---------- ----------
789 7

Related

Insert record from one table to another table - Oracle

I have a table TABLE1 which has 5 columns (ROLL_NO, NAME, UNITS, CODE, AMOUNT);
CREATE TABLE TABLE1 (ROLL_NO VARCHAR2(3), NAME VARCHAR2(4), UNITS NUMBER, AMOUNT NUMBER, CODE VARCHAR2(3));
------------------------------------------------------------------------------------------
INSERT INTO TABLE1 VALUES ('101', 'JOHN', 1, 6, 'ABC');
INSERT INTO TABLE1 VALUES ('101', 'JOHN', 2, 6, 'ABC');
INSERT INTO TABLE1 VALUES ('102', 'TOMS', 1, 7, 'ABC');
INSERT INTO TABLE1 VALUES ('102', 'TOMS', 6, 7, 'ABC');
INSERT INTO TABLE1 VALUES ('103', 'FINN', 1, 1, 'BCD');
ROLL_NO NAME UNITS AMOUNT CODE
-------------------------------------------------------
101 JOHN 1 6 ABC
101 JOHN 2 6 ABC
-------------------------------------------
102 TOMS 1 7 ABC
102 TOMS 6 7 ABC
103 FINN 1 1 BCD
There is second table TABLE2 where we need to insert data from TABLE1
CREATE TABLE TABLE2 (ROLL_NO VARCHAR2(3), NAME VARCHAR2(4), RESULT VARCHAR2(3));
There are three conditions to insert data into TABLE2
1st case : If CODE is 'ABC' and SUM(UNITS) of particular ROLL_NO is equal to AMOUNT then don't insert data into TABLE2
2nd case : If CODE is 'ABC' and SUM(UNITS) of particular ROLL_NO is not equal to AMOUNT then insert data with RESULT column value as 'YES'
3rd case : If CODE is not 'ABC' then RESULT column will be 'YES'.
Note: NAME, CODE and AMOUNT will be same for particular ROLL_NO though ROLL_NO has multiple UNITS.
Example :
ROLL_NO 102 CODE 'ABC' and two lines with SUM(UNITS) as 7 and its equal to AMOUNT i.e. 7 and (1st case)
ROLL_NO 101 has CODE 'ABC' and two lines with SUM(UNITS) as 3 and its not equal to AMOUNT i.e. 6 (2nd case)
ROLL_NO 103 has CODE 'BCD' which is not equal to 'ABC'(3rd case)
At the end TABLE2 should have
ROLL_NO NAME RESULT
-----------------------------
101 JOHN YES
103 FINN YES
I have tried this oracle query but it is inserting data related to 102 ROLL_NO which I don't need
SELECT T1.ROLL_NO, T1.NAME,
CASE
WHEN T1.CODE <> 'ABC' THEN 'YES'
WHEN T1.CODE = 'ABC' AND T2.TOT_UNITS <> T1.AMOUNT THEN 'YES'
END RESULT
FROM (SELECT DISTINCT ROLL_NO, NAME, AMOUNT, CODE
FROM TABLE1 ) T1
JOIN (SELECT ROLL_NO, SUM(UNITS) AS TOT_UNITS
FROM TABLE1
GROUP BY ROLL_NO) T2 ON T1.ROLL_NO = T2.ROLL_NO
I am not able to figure out how to not insert ROLL_NO 102 record into TABLE2..Can anyone provide better query than this if possible? Thank you
A "better" option is to scan table1 only once.
SQL> insert into table2 (roll_no, name, result)
2 with temp as
3 (select roll_no, name, sum(units) sum_units, amount, code,
4 case when code = 'ABC' and sum(units) = amount then 'NO'
5 when code = 'ABC' and sum(units) <> amount then 'YES'
6 else 'YES'
7 end as result
8 from table1
9 group by roll_no, name, amount, code
10 )
11 select roll_no, name, result
12 from temp
13 where result = 'YES';
2 rows created.
SQL> select * from table2;
ROL NAME RES
--- ---- ---
101 JOHN YES
103 FINN YES
SQL>

ORACLE : How to use manual ID generated using MAX ID with Oracle Merge statement insert query

I have 2 tables like below,
Master_Data_1
Id Name
1 AAA
2 BBB
3 DDD
4 CCC
Master_Data_2
Id Name Upt_Flg
1 DDD False
2 EEE False
3 FFF False
both tables have same ID but different Name, and ID field is neither auto incremented nor sequence. But ID is a not null primary key column which will be generated based on MAX ID logic.
In this case i am trying to merge Master_Data_1 table with Master_Data_2 table using oracle merge statement.
So i am having issue in WHEN NOT MATCHED THEN case, i am trying to insert not matched records in to Master_data_2 table from master_data_1 table.
In this scenario ID in Master_Data_2 table will not be auto incremented, and also i cannot use the source table ID here because it will lead to unique constraint exception.
Note : I don't want to alter a table to make ID auto increment or adding sequence for ID.
Expected Output in Master_Data_2 table using merge query:
Id Name Upt_Flg
1 DDD TRUE
2 EEE False
3 FFF False
4 AAA False
5 BBB False
6 CCC False
is there any other way to achieve this?
I guess ROW_NUMBER analytic function might help you here.
MERGE INTO Master_Data_2 md2
USING (SELECT (SELECT MAX(id) FROM Master_Data_2) + ROW_NUMBER() OVER(ORDER BY id) new_id
,name
FROM Master_Data_1
) md1
ON (md2.name = md1.name)
WHEN MATCHED THEN UPDATE
SET Upt_flg = 'TRUE'
WHEN NOT MATCHED THEN
INSERT (md2.id, md2.name)
VALUES (Md1.new_id, md1.name);
Here is the fiddle
You can simply achieve it using INSERT and MINUS operator as following:
insert into master_data_2
select
(select max(id) from master_data_2) + row_number() over (order by 1),
name
from
(select name from master_data_1
minus
select name from master_data_2)
db<>fiddle demo
Cheers!!

how to get the length of the string in sqlcl

i am trying to display the top three rows based on their length of the string in names.but the system just reads the predefined length of the string column not the string in the column
SQL> select max(length(name)) from cus_detail;
MAX(LENGTH(NAME))
-----------------
10
SQL> select *
from (select id, name, length(name) as namelen, distance
from cus_detail
order by length(name) desc
)
where rownum<=3;
ID NAME NAMELEN DISTANCE
---------- ---------- ---------- ----------
1 paul 10 15
2 baul 10 15
3 mereum 10 20
That's what CHAR datatype does - it right-pads value with spaces up to the full column length:
SQL> create table test (name char(10));
Table created.
SQL> insert into test (name) values ('London');
1 row created.
SQL> select max(length(name)) from test;
MAX(LENGTH(NAME))
-----------------
10
SQL>
A closer look:
SQL> select '#' || name ||'#' name, dump(name) dmp from test;
NAME DMP
------------ --------------------------------------------------
#London # Typ=96 Len=10: 76,111,110,100,111,110,32,32,32,32
^^^^ L o n d o n ^^^^^^^^^^^
spaces spaces
So, you could trim the value:
SQL> select max(length(trim(name))) from test;
MAX(LENGTH(TRIM(NAME)))
-----------------------
6
SQL>
or - even better - change column's datatype to varchar2.

PLSql stored procedure to convert data of column in select statement

I want to create a pl/sql procedure in which I want to retrieve the value of column from a table based on another column and I want the output as select query having the field values of the column as the column name.
Suppose I have a table having two columns as
test1:
column 1 column 2
-----------------
abc 123
abc 234
abc 453
abab 4546
abab 454665
abab 4564566
I want the result as select 123, 234, 453 from abc when I provide the input variable for column 1
You can use the below query in procedure to retreive the result:
select listagg(column2, ',') within group (order by column1) from test1
where column1 = 'abc';

how to match an integer with varchar containing digits separated by commas in oracle

I am facing a strange scenario where I need to match an integer with varchar containing digits separated by commas in oracle
Example:
Table t1:
id integer
key integer
Table t2
id integer,
keys varchar2
T1 values are:
1,111
2,201
3,301
T2 values are:
1, "111,301"
2, "111,201"
3, "201,301"
PROBLEM: Is there any way I can match or regular_expression match with key of T1 with keys of T2?
you can do a regular join without regex for this:
select *
from t1
inner join t2
on ','||t2.keys||',' like '%,'||to_char(t1.key)||',%';
eg:
SQL> create table t1(id, key)
2 as
3 select 1, 111 from dual union all
4 select 2, 201 from dual union all
5 select 3, 301 from dual;
Table created.
SQL> create table t2(id, keys)
2 as
3 select 1, '111,301' from dual union all
4 select 2, '111,201' from dual union all
5 select 3, '201,301' from dual;
Table created.
SQL> select *
2 from t1
3 inner join t2
4 on ','||t2.keys||',' like '%,'||to_char(t1.key)||',%';
ID KEY ID KEYS
---------- ---------- ---------- -------
1 111 1 111,301
1 111 2 111,201
2 201 2 111,201
2 201 3 201,301
3 301 1 111,301
3 301 3 201,301
6 rows selected.
It's not regex, just concatenation. For example lets say we wanted to compare
KEY KEYS
111 111,301
we could say
where keys like '%'||key||'%'
i.e. expanded, this is
where '111,301' like '%111%'
which matches fine. But I added some commas there too. ie I did this:
where ',111,301,' like '%,111,%'
Why? imagine instead you had this data:
KEY KEYS
111 1111,301
If we did the simple join:
where '1111,301' like '%111%'
it would incorrectly match. By injecting leading and trailing commas on both sides:
where ',1111,301,' like '%,111,%'
is no longer erroneously matches, as ,1111, isn't like ,111,.

Resources