Convert String to char in oracle - sql

Hi i have the following data '1,2,3' and i need to convert this into this '1','2','3' that i will use in this
Select * from dual where to_chat(month) in ('1','2','3')
i cannot use query straight like that because of the quater
Quater no. Month
1 1,2,3
2 4,5,6
...
so i must use case like this but case statement return on format like this '1','2','3'
Select * from dual
where to_chat(month) in (
select
case quarter
when 1 then '1','2','3'
when 2 then '4','5','6'
end
from dual )
input
'1,2,3'
expected output
'1','2','3'

You can use regexp_like():
where regexp_like(<whatever>, replace('1,2,3', ',', '|'))
Putting single quotes in the string still won't enable you to do what you want with like. It will still be a single string, but one that has single quotes and commas in it.

How about such an approach? Example is based on Scott's EMP table. I'd like to fetch employees which were hired in certain months.
Sample data:
SQL> select deptno, ename, job, hiredate, to_char(hiredate, 'mm') mon from emp order by mon;
DEPTNO ENAME JOB HIREDATE MO
---------- ---------- --------- ---------- --
20 ADAMS CLERK 12.01.1983 01
10 MILLER CLERK 23.01.1982 01
30 ALLEN SALESMAN 20.02.1981 02 -- suppose I want to select employees
30 WARD SALESMAN 22.02.1981 02 -- hired in February,
20 JONES MANAGER 02.04.1981 04 -- April and
30 BLAKE MANAGER 01.05.1981 05 -- May
10 CLARK MANAGER 09.06.1981 06
30 TURNER SALESMAN 08.09.1981 09
30 MARTIN SALESMAN 28.09.1981 09
10 KING PRESIDENT 17.11.1981 11
20 SCOTT ANALYST 09.12.1982 12
20 SMITH CLERK 17.12.1980 12
30 JAMES CLERK 03.12.1981 12
20 FORD ANALYST 03.12.1981 12
14 rows selected.
Query - which splits input search string into rows (so that you could use it in IN clause) would then be:
SQL> with src as
2 (select &par_month src_month from dual)
3 select deptno, ename, job, hiredate
4 from emp
5 where to_number(to_char(hiredate, 'mm')) in
6 (select regexp_substr(src_month, '[^,]+', 1, level)
7 from src
8 connect by level <= regexp_count(src_month, ',') + 1
9 )
10 order by to_char(hiredate, 'mm');
Enter value for par_month: '2,4,5'
DEPTNO ENAME JOB HIREDATE
---------- ---------- --------- ----------
30 ALLEN SALESMAN 20.02.1981
30 WARD SALESMAN 22.02.1981
20 JONES MANAGER 02.04.1981
30 BLAKE MANAGER 01.05.1981
SQL>

Related

Multiple table outputs based on one query

I have one table that has 12 conditions (months). I need to produce 12 outputs (tables) for select statements where the only thing that changes is that one condition (month).
Example:
SELECT * FROM table WHERE month = 01;
SELECT * FROM table WHERE month = 02;
SELECT * FROM table WHERE month = 03;
etc.
In reality, the code is pretty large and chunky, I don't feel like copy pasting it numerous times just to change one condition.
Is there a way to write one statement to produce different outputs based on changing condition?
It looks pretty basic to me, but I can't find the answer.
It doesn't sound like a good approach, but without a fuller picture of the task it's hard to say.
What you can do is generate a list of numbers and use it to produce your required statements, such as:
with months as (
select 1 m
union all
select m + 1 from months
where m<12
)
select Concat('select * from table where month = ', m, ';')
from months
Depending on your requirements and RDBMS you can either use them directly in your IDE or dynamically execute.
In Oracle, you could use hierarchical query to generate months; something like this:
SQL> select empno,
2 ename,
3 job,
4 to_char(hiredate, 'fmMonth', 'nls_date_language = english') month
5 from emp
6 where extract(month from hiredate) in (select level from dual
7 connect by level <= 12
8 )
9 order by extract (month from hiredate);
EMPNO ENAME JOB MONTH
---------- ---------- --------- ------------------------------------
7876 ADAMS CLERK January
7934 MILLER CLERK January
7499 ALLEN SALESMAN February
7521 WARD SALESMAN February
7566 JONES MANAGER April
7698 BLAKE MANAGER May
7782 CLARK MANAGER June
7844 TURNER SALESMAN September
7654 MARTIN SALESMAN September
7839 KING PRESIDENT November
7788 SCOTT ANALYST December
7369 SMITH CLERK December
7900 JAMES CLERK December
7902 FORD ANALYST December
14 rows selected.
SQL>
Can be as simple as left/right join to cte months
declare #table table (mm smallint,somedata varchar(20))
insert into #table
values
(1,'some data for 1')
,(3,'some data for 3')
,(5,'some data for 5')
;with cte_months as (
select 1 mm
union all
select mm + 1 from cte_months
where mm<12
)
select c.mm,t.somedata from #table t
right join cte_months c on t.mm = c.mm

bind parameter in oracle EBS

i need to add list of values to a bin parameter on report builder in oracle e-business suite
but in this list of values i need the first option is all and other values are result of select statement like the following:
all
10
20
30
....
so if the user clicked on "all" the report will query all departments
if the user clicked on any other specific department, the report will query this specific department
how can i add this "all" option??
I don't use EBS, but I do know Reports and some SQL so - here's my suggestion.
Adding the "all" option is simple - union it with other values. Something like this:
SQL> select value
2 from (select 1 rn, 'all' value from dual
3 union all
4 select 2 rn, to_char(deptno) from dept
5 )
6 order by rn, value;
VALUE
----------------------------------------
all
10
20
30
40
SQL>
Then, in a query, you'd use it as
select e.deptno, e.ename, e.job
from emp e
where e.deptno = case when :par_deptno = 'all' then to_char(e.deptno)
else :par_deptno
end
order by e.deptno, e.ename;
The above example, ran in SQL*Plus (so don't mind a substitution instead of a bind variable):
First, I'm passing 10:
SQL> select e.deptno, e.ename, e.job
2 from emp e
3 where e.deptno = case when '&&par_deptno' = 'all' then to_char(e.deptno)
4 else '&&par_deptno'
5 end
6 order by e.deptno, e.ename;
Enter value for par_deptno: 10
DEPTNO ENAME JOB
---------- ---------- ---------
10 CLARK MANAGER
10 KING PRESIDENT
10 MILLER CLERK
Now, let's try all:
SQL> undefine par_deptno
SQL> /
Enter value for par_deptno: all
DEPTNO ENAME JOB
---------- ---------- ---------
10 CLARK MANAGER
10 KING PRESIDENT
10 MILLER CLERK
20 ADAMS CLERK
20 FORD ANALYST
20 JONES MANAGER
20 SCOTT ANALYST
20 SMITH CLERK
30 ALLEN SALESMAN
30 BLAKE MANAGER
30 JAMES CLERK
30 MARTIN SALESMAN
30 TURNER SALESMAN
30 WARD SALESMAN
14 rows selected.
SQL>
Looks OK to me. Now, how will it look like in EBS, I have no idea.

Use substitution variable within Oracle IN clause

I'm trying to write a simple query where the requirement is to use a substitution variable that can be used to enter mutiple possible values for a column that's used for filtering the query.
The reqiurement is to produce the following query
select
CONTRACT,
ORDER_NO,
CUSTOMER_NO
from CUSTOMER_ORDER
where state='Picked'
and contract in ('ABC','DEF')
but the contract values will need to be entered during runtime by means of a substitution variable. I'm working with the limitation of only being able to write a static SQL Query ("select ..from..where..") and no dynamic code can be written inside pl sql blocks.
So, what I tried was the following,
select
CONTRACT,
ORDER_NO,
CUSTOMER_NO
from CUSTOMER_ORDER_JOIN
where contract in (select '''' || REPLACE('&CONTRACT',';',''',''') || '''' from dual)
When the prompt appears for the substitution, I enter ABC;DEF
But this doesn't seem to work. Although when I run the following separately,
select '''' || REPLACE('&CONTRACT',';',''',''') || '''' from dual
I get 'ABC','DEF' as the result.
Why is this not working? Is there a way to achieve my desired result ?
Thanks
One option is to split those values into rows and use them as a subquery.
Example based on Scott's EMP table:
SQL> select ename, job, sal from emp;
ENAME JOB SAL
---------- --------- ----------
SMITH CLERK 920
ALLEN SALESMAN 1600
WARD SALESMAN 1250
JONES MANAGER 2975
MARTIN SALESMAN 1250
BLAKE MANAGER 2850
CLARK MANAGER 2450
SCOTT ANALYST 3000
KING PRESIDENT 10000
TURNER SALESMAN 1500
ADAMS CLERK 1100
JAMES CLERK 950
FORD ANALYST 3000
MILLER CLERK 1300
14 rows selected.
SQL> select ename, job, sal
2 from emp
3 where ename in (select regexp_substr(replace(q'[&&par_ename]', chr(39), ''), '[^,]+', 1, level)
4 from dual
5 connect by level <= regexp_count(q'[&&par_ename]', ',') + 1
6 );
Enter value for par_ename: 'SMITH','ALLEN'
ENAME JOB SAL
---------- --------- ----------
SMITH CLERK 920
ALLEN SALESMAN 1600
SQL>
Alternatively, use sys.odcivarchar2list:
SQL> select ename, job, sal
2 from emp
3 where ename in (select column_value
4 from table(sys.odcivarchar2list(&par_ename))
5 );
Enter value for par_ename: 'SMITH','ALLEN'
ENAME JOB SAL
---------- --------- ----------
SMITH CLERK 920
ALLEN SALESMAN 1600
SQL>
It works without single quotes as well:
SQL> Select ename, job, sal
2 from emp
3 where ename in (select regexp_substr(replace(q'[&&par_ename]', chr(39), ''), '[^,]+', 1, level)
4 from dual
5 connect by level <= regexp_count(q'[&&par_ename]', ',') + 1
6 );
Enter value for par_ename: SMITH,ALLEN,KING
ENAME JOB SAL
---------- --------- ----------
SMITH CLERK 920
ALLEN SALESMAN 1600
KING PRESIDENT 10000
SQL>

Oracle- sql query to print odd number of rows when we do not have number data type columns

I was trying to print odd numbers of rows from my table without taking taking help of my numeric cloumns
when I try to execute this query I was getting only first row.
select * from emp3 where mod(rownum,2)=1;
emp3 is my table name.
and when I use my one of the numeric columns in place of rownum I was getting desired output.
select * from emp3 where mod(eid,2)=1 order by eid;
where eid is a numeric column in the table.
But what if do not have a numeric column and I want to print only odd number of rows from the table?
Help me!
Try to execute the below query
select * from (select rownum rn ,column from column_name) where mod(rn,2) <> 0
and please refer to this link for better understanding the concept of rownum https://www.youtube.com/watch?v=QMyw1jumGyQ
If the EID column isn't numeric, then use something that is. For example, ROW_NUMBER gives such an information:
SQL> with temp as
2 (select empno, ename, job sal,
3 row_number() over (order by null) rn
4 from emp
5 )
6 select *
7 from temp
8 where mod(rn, 2) = 1;
EMPNO ENAME SAL RN
---------- ---------- --------- ----------
7369 SMITH CLERK 1
7521 WARD SALESMAN 3
7654 MARTIN SALESMAN 5
7782 CLARK MANAGER 7
7839 KING PRESIDENT 9
7876 ADAMS CLERK 11
7902 FORD ANALYST 13
7 rows selected.
SQL>
Or even ROWNUM you already tried to use:
SQL> with temp as
2 (select empno, ename, job sal,
3 rownum rn
4 from emp
5 )
6 select *
7 from temp
8 where mod(rn, 2) = 1;
EMPNO ENAME SAL RN
---------- ---------- --------- ----------
7369 SMITH CLERK 1
7521 WARD SALESMAN 3
7654 MARTIN SALESMAN 5
7782 CLARK MANAGER 7
7839 KING PRESIDENT 9
7876 ADAMS CLERK 11
7902 FORD ANALYST 13
7 rows selected.
SQL>

Deleting duplicate records with ROWNUM?

I know how to delete duplicate records with ROWID.
Please guide me to delete duplicate records with ROWNUM in Oracle.
That just won't work. From documentation:
For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on.
Its value is set at the moment you run the query and can be changed, depending on how you fetch data (different ORDER BY will produce different ROWNUM value for the same row). As it is sequential, you can't set "groups" of ROWNUM values (for example, so that it goes from 1, 2, 3 for one set, then 1, 2, 3, 4, 5 for another - you'll always get 1, 2, 3, 4, 5, 6, 7, 8).
If you planned to do something like this:
SQL> create table test as
2 select e.empno, e.deptno, d.dname, e.ename
3 from emp e join dept d on e.deptno = d.deptno;
Table created.
SQL> select * from test order by deptno;
EMPNO DEPTNO DNAME ENAME
---------- ---------- -------------- ----------
7782 10 ACCOUNTING CLARK
7839 10 ACCOUNTING KING
7934 10 ACCOUNTING MILLER
7369 20 RESEARCH SMITH
7902 20 RESEARCH FORD
7566 20 RESEARCH JONES
7900 30 SALES JAMES
7844 30 SALES TURNER
7654 30 SALES MARTIN
7521 30 SALES WARD
7499 30 SALES ALLEN
7698 30 SALES BLAKE
12 rows selected.
SQL> delete from test t
2 where t.empno in (select a.empno
3 from (select t1.empno, t1.deptno, t1.dname, rownum rn
4 from test t1
5 ) a
6 where a.rn > 1
7 );
11 rows deleted.
As you can see, all rows (but one) are duplicates. Here's why:
SQL> rollback;
Rollback complete.
SQL> select a.deptno, a.empno, a.rn, a.rn1
2 from (select t1.empno, t1.deptno, t1.dname, rownum rn,
3 row_number() over (partition by t1.deptno order by null) rn1
4 from test t1
5 ) a;
DEPTNO EMPNO RN RN1
---------- ---------- ---------- ----------
10 7782 2 1
10 7839 1 2
10 7934 3 3
20 7369 5 1
20 7902 4 2
20 7566 6 3
30 7900 7 1
30 7844 8 2
30 7654 9 3
30 7521 10 4
30 7499 11 5
30 7698 12 6
12 rows selected.
See? RN (ROWNUM) has all values from 1, 2, ..., 12. RN1 (ROW_NUMBER, which allows us to set partitions) does the job correctly. So, if you used RN1 instead of RN, it would work:
SQL> delete from test t
2 where t.empno in (select a.empno
3 from (select t1.empno, t1.deptno, t1.dname, rownum rn,
4 row_number() over (partition by t1.deptno order by null) rn1
5 from test t1
6 ) a
7 where a.rn1 > 1
8 );
9 rows deleted.
SQL> select * From test;
EMPNO DEPTNO DNAME ENAME
---------- ---------- -------------- ----------
7782 10 ACCOUNTING CLARK
7369 20 RESEARCH SMITH
7900 30 SALES JAMES
SQL>
[EDIT: deleting duplicates #2]
Here's another example which shows how/what to do if you want to delete duplicates. It is based on the "ROWID technique" (although there are another ones too).
Back to the table we've been working with. Suppose that we want to keep only one distinct job per department:
SQL> select deptno, job, dname, empno, ename
2 from test
3 order by deptno, job;
DEPTNO JOB DNAME EMPNO ENAME
---------- --------- -------------- ---------- ----------
10 CLERK ACCOUNTING 7934 MILLER
10 MANAGER ACCOUNTING 7782 CLARK
10 PRESIDENT ACCOUNTING 7839 KING
20 ANALYST RESEARCH 7902 FORD
20 CLERK RESEARCH 7369 SMITH
20 MANAGER RESEARCH 7566 JONES
30 CLERK SALES 7900 JAMES
30 MANAGER SALES 7698 BLAKE
30 SALESMAN SALES 7844 TURNER -- leave
30 SALESMAN SALES 7654 MARTIN -- only
30 SALESMAN SALES 7521 WARD -- one
30 SALESMAN SALES 7499 ALLEN -- salesman
12 rows selected.
in department 10, there are no duplicates - 3 employees, each of them doing their own job
the same goes for department 20
however, in department 30, there are 4 SALESMEN and we want to keep only one - another ones are duplicates
It means that you have to take both columns - DEPTNO and JOB - into account when deleting rows. Let's do that:
SQL> delete from test a
2 where rowid > (select min(rowid)
3 from test b
4 where a.deptno = b.deptno --> take both DEPTNO ...
5 and a.job = b.job --> and JOB into account
6 );
3 rows deleted.
The result: departments 10 and 20 didn't change, but in department 30 now we have only one salesman, just as we wanted:
SQL> select deptno, job, dname, empno, ename
2 from test
3 order by deptno, job;
DEPTNO JOB DNAME EMPNO ENAME
---------- --------- -------------- ---------- ----------
10 CLERK ACCOUNTING 7934 MILLER
10 MANAGER ACCOUNTING 7782 CLARK
10 PRESIDENT ACCOUNTING 7839 KING
20 ANALYST RESEARCH 7902 FORD
20 CLERK RESEARCH 7369 SMITH
20 MANAGER RESEARCH 7566 JONES
30 CLERK SALES 7900 JAMES
30 MANAGER SALES 7698 BLAKE
30 SALESMAN SALES 7844 TURNER
9 rows selected.
SQL>