Case, Decode or PlSQL
Hello,
I am new to Oracle. I have a, hopefully basic SQL question.
There is sometime four users in my dbs. But, I would like make query where the users below are returned, even if not in db.
1. Bob
2. Jane
3. John
4. Abul
I have rows in db:
ROWS IN DB
Username account status
bob Support Active
Jane Dev Active
John Dev Expired
How I can write query to find all users, if one is missing. Try to get format
Bob's Support account is active
Jane's Dev account is active
John's Dev account is active
Abul is not in db
I try CASE and Decode, but get bad returns.
Pls help.
Tring to learn SQL. Go to class in three weeks.
Hi,
Welcome to the forum!
So you have four special users, each with a name and id number. That sounds like data. Data belongs in tables. You should create a table that has four rows. Then you could use that table to do an outer-join with other tables, such as db.
If you don't have such a table, you can generate a result set on the fly that will serve as a table. The sub-query special_users below is just that:
WITH special_users AS
SELECT 'Abul' AS username FROM dual UNION ALL
SELECT 'BOB' FROM dual UNION ALL
SELECT 'Jane' FROM dual UNION ALL
SELECT 'John' FROM dual
SELECT su.username
|| CASE
WHEN db.username IS NULL
THEN ' is not in db'
ELSE '''s ' || account
|| ' account is '
|| status
END AS msg
FROM special_users su
LEFT OUTER JOIN db ON db.username = su.username
;If you do have a real special_users table, then the main query above works;l just skip the WHERE clause (the forst 7 lines) and, the query is:
SELECT su.username
|| CASE
WHEN db.username IS NULL
THEN ' is not in db'
ELSE '''s ' || account
|| ' account is '
|| status
END AS msg
FROM special_users su
LEFT OUTER JOIN db ON db.username = su.username
;Edited by: Frank Kulash on Sep 28, 2009 3:53 PM
The subject line you chose for this message, "Case, Decode or PlSQL" is very good, and shows the order in which you should try things.
(1) CASE is the general way to handle if-then-else logic in a SQL expression
(2) DECODE (and other specialized features, such as NVL2, which Michaels used) can save you a little typing in special circumstances. Once you have mastered CASE, you can start exploring these other expressions.
(3) PL/SQL is the last resort, used only if there is no good way to do something in SQL.
Similar Messages
-
CASE/DECODE in WHERE caluse
Hi friends,
Let's consider an EMP table has the following structure and data:
create table EMP
EMPNO NUMBER(4) not null,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2),
CONFDATE DATE
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7369, 'SMITH', 'CLERK', 7902, to_date('17-12-1980', 'dd-mm-yyyy'), 800, null, 20, to_date('27-12-1980', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7499, 'ALLEN', 'SALESMAN', 7698, to_date('20-02-1981', 'dd-mm-yyyy'), 1600, 300, 30, to_date('28-02-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7521, 'WARD', 'SALESMAN', 7698, to_date('22-02-1981', 'dd-mm-yyyy'), 1250, 500, 30, to_date('28-02-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7566, 'JONES', 'MANAGER', 7839, to_date('02-04-1981', 'dd-mm-yyyy'), 2975, null, 20, to_date('12-04-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7654, 'MARTIN', 'SALESMAN', 7698, null, 1250, 1400, 30, to_date('28-09-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7698, 'BLAKE', 'MANAGER', 7839, to_date('01-05-1981', 'dd-mm-yyyy'), 2850, null, 30, to_date('11-05-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7782, 'CLARK', 'MANAGER', 7839, to_date('09-06-1981', 'dd-mm-yyyy'), 2450, null, 10, to_date('19-06-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7788, 'SCOTT', 'ANALYST', 7566, null, 3000, null, 20, to_date('09-12-1982', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7839, 'KING', 'PRESIDENT', null, to_date('17-11-1981', 'dd-mm-yyyy'), 5000, null, 10, to_date('27-11-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7844, 'TURNER', 'SALESMAN', 7698, to_date('08-09-1981', 'dd-mm-yyyy'), 1500, 0, 30, to_date('18-09-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7876, 'ADAMS', 'CLERK', 7788, null, 1100, null, 20, to_date('12-01-1983', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7900, 'JAMES', 'CLERK', 7698, null, 950, null, 30, to_date('03-12-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7902, 'FORD', 'ANALYST', 7566, to_date('03-12-1981', 'dd-mm-yyyy'), 3000, null, 20, to_date('13-12-1981', 'dd-mm-yyyy'));
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
values (7934, 'MILLER', 'CLERK', 7782, to_date('23-03-1981', 'dd-mm-yyyy'), 1300, null, 10, to_date('31-05-1981', 'dd-mm-yyyy'));
commit;
Now I need to fetch the employees whose hire date is between 01-APR-1981 and 31-DEC-1981. If the hire date is null, then confirmation date has to be considered.
For this input the following employees's records should be returned:
7566
7654
7698
7782
7839
7844
7900
7902
I tried with CASE, DECODE in WHERE clause. But I couldn't succeed. Please help.
Thanks in advance.
IniyavanSQL> ed
Wrote file afiedt.buf
1* select * from emp_test where nvl(hiredate,confdate) between '01-APR-1981' and '31-DEC-1981'
SQL> /
EMP_TESTNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO CONFDATE
7566 JONES MANAGER 7839 02-APR-81 2975 20 12-APR-81
7654 MARTIN SALESMAN 7698 1250 1400 30 28-SEP-81
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 11-MAY-81
7782 CLARK MANAGER 7839 09-JUN-81 2450 10 19-JUN-81
7839 KING PRESIDENT 17-NOV-81 5000 10 27-NOV-81
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30 18-SEP-81
7900 JAMES CLERK 7698 950 30 03-DEC-81
7902 FORD ANALYST 7566 03-DEC-81 3000 20 13-DEC-81
8 rows selected.@boopathi: Why to_char is needed here ? Further to_char(hire date,'DD_MON_YY') and comparing with '01-APR-1981' ? and WHAT is "_" doing in date format ? You sholud test your query before posting.
Edited by: Saubhik on May 17, 2010 11:33 PM -
Hello All,
my table1 below
FILE_ID
1
2
3Table2
FILE_ID, FILE_NAME, P_FILE_ID
11 pdp01 1
12 pdp02 1
13 pdp03 1I am trying something like this
select case WHEN d.file_name LIKE '%01%' THEN d.file_id
end 01_file_id_value,
case WHEN d.file_name LIKE '%02%' THEN d.file_id
end 02_file_id_value
from TABLE1 r , TABLE2 d
where d.p_file_id = r.file_id'I am receiving something like
01_file_id_value 02_file_id_value
11
12I need something like
01_file_id_value 02_file_id_value
11 12I am not sure if we can do this with case/decode please help/guide meHi,
It looks like you want an aggregate query, something like this:
select MIN ( case
WHEN d.file_name LIKE '%01%' THEN d.file_id
end
) AS "01_file_id_value", -- non-standard alias must be in double-quotes
MIN ( case
WHEN d.file_name LIKE '%02%' THEN d.file_id
end
) AS "02_file_id_value" -- non-standard alias must be in double-quotes
from TABLE1 r
, TABLE2 d
where d.p_file_id = r.file_id
;What results would you want if there were two (or more) non-NULL values in the same column?
Post a little sample data (CREATE TABLE and INSERT statements) for all tables, and also post the results you want from that data.
Explain, using specific examples, how you get those results from that data.
Always say which version of Oracle you're using. -
No output for XML Publisher Report using CASE/DECODE in Where Clause
Hi,
I've a business requirement to modify an existing report which has two input parameters,
-> p_statcode (Closed Status) which can have values 'Y' or 'N'
-> p_overdue (Overdue Flag) which can have values 'Y' or 'N'
The Overdue Flag is an evaluated column having values of Y/N and it is evaluated as follows,
ONTF_MOD_VAL(NVL (
(TRUNC (SYSDATE)
- (TO_DATE (oe_order_lines.attribute18,
'DD-MON-RRRR')
+ TO_NUMBER (fnd_lookup_values.meaning))),
0
overdue_flagThe user requirement now is they needs to be a third option for parameter p_overdue called ALL,
passing which the output should include records having
p_statcode is Y ELSE p_statcode is N AND p_overdue is Y OR p_overdue is N
In other words records having both Y and N vlaues for Overdue Flag have to be returned irrespective of the value given to Closed Status.
Original where clause in the Data Definition file is as follows,
WHERE Closed_Status = nvl(:p_statcode,Closed_Status)
AND overdue_flag = nvl(:p_overdue,overdue_flag)My modified code is as follows,
WHERE Closed_Status = NVL (:p_statcode, Closed_Status)
AND overdue_flag = (CASE
WHEN :p_overdue = 'Y' THEN 'Y'
WHEN :p_overdue = 'N' THEN 'N'
ELSE overdue_flag
END)
OR
WHERE Closed_Status = NVL (:p_statcode, Closed_Status)
AND overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag)Both approaches have the same problem.
The output is in EXCEL format. The modified query works fine for p_overdue as Y or N but when p_overdue is passed as ALL it returns an empty EXCEL sheet with just the report output column headers.
Any help as to why this is the case ?? What is wrong in my approach ?
Regards,
Vishalnot clear about p_overdue = ALL
which values needed for p_overdue = ALL ?
try smth like
WHERE Closed_Status = NVL (:p_statcode, Closed_Status)
AND (
overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag) and :p_overdue != 'ALL'
or
:p_overdue = 'ALL' and (overdue_flag = 'Y' or overdue_flag = 'N')
)for overdue_flag which has more then 'Y', 'N' values
if overdue_flag only in ('Y','N') then
WHERE Closed_Status = NVL (:p_statcode, Closed_Status)
AND (
overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag) and :p_overdue != 'ALL'
or
:p_overdue = 'ALL'
) -
Case Decode - invalid column name error
select Workweek, max( decode( Type, T34, prct, null ) ) Bad,
max( decode( Type, T35, prct, null ) ) Repair,
max( decode( Type, T36, prct, null ) ) Good
FROM
(select Workweek, Type, round(ratio_to_report(sum(Testtime_in_Minutes)) over(partition by Workweek)*100,3) prct
FROM
(select ts.lot as Lot, ts.wafer_id as Wafer, dt.SORT_X as X, dt.SORT_Y as Y, ts.devrevstep as PRODUCT, ts.operation as OPERATION, dt.INTERFACE_BIN as INTERFACE_BIN, (dt.TEST_TIME)/60.0 as Testtime_in_Minutes,
ts.TEST_END_DATE_TIME as Test_End_Time, ts.Program_Name, ts.test_end_work_week as Workweek,
(CASE
WHEN (dt.INTERFACE_BIN > 9 AND dt.INTERFACE_BIN < 15) THEN 'T34'
WHEN (dt.INTERFACE_BIN =30 OR dt.INTERFACE_BIN =31 OR dt.INTERFACE_BIN = 32 OR dt.INTERFACE_BIN = 33) THEN 'T35'
ELSE 'T36'
END ) Type
from a_testing_session ts, a_device_testing dt
where ts.test_end_work_week >= 200715
and (ts.devrevstep like '9600%')
and dt.lao_start_ww = ts.test_end_work_week
and dt.ts_id = ts.ts_id)
GROUP BY Workweek, Type)
This sql query above does not run properly, gives invalid column name error. However, the entire select statement surrounded by the () works. There must be an error in the first 4 lines someplace, but I do not see it.Assuming type is a string, I assume you meant
MAX( DECODE( type, 'T34', prct, NULL )) Badwhere T34 is a string literal. Otherwise, you'd need to have columns named T34, T35, and T36 in your inner select.
One note, though, it's probably a bad idea to have a column named Type. While it's legal to do so, TYPE is a keyword in SQL, so that name will at a minimum be confusing.
Justin -
Owb 9 Case / decode statement
Hi all,
We using owb 9. Case staments can not be used in this version of owb. Could be done with a decode statement.
But decode statements requires a static value to result a value.
In my statement i want to use less the or greater the staments. How can i do that in a decode.
I found out a decode does also not work. anyone a idea. except for using a view as source
so a example what i want:
a < 180 then 1
a between 180 and 200 then 2
a > 200 then 3
tnx in advanced
Edited by: user565199 on 22-jun-2011 3:59Hi ,
Did you try with case statement, if you try with case what error your getting?
Thanks,
Praveen -
Update statement that includes case, decode and from clause
hello
I've the following code. I ran this code in 9i and got the errror SQL command not properly ended. Can I use FROM clause in an update statement?
CREATE OR REPLACE procedure NRI
IS
BEGIN
UPDATE IEB2 SET SDI =
(CASE PSDI WHEN '11' THEN '16'
WHEN '13' THEN '38'
WHEN '14' THEN '18'
WHEN '23' THEN '21'
WHEN '24' THEN '21'
WHEN '31' THEN '27'
WHEN '32' THEN '37'
WHEN '33' THEN '38'
WHEN '34' THEN '37'
WHEN '43' THEN '46'
WHEN '53' THEN '45'
WHEN '55' THEN '48'
WHEN '60' THEN '54'
WHEN '61' THEN '57'
WHEN '62' THEN '54'
WHEN '63' THEN '56'
WHEN '64' THEN '52'
WHEN '70' THEN '21'
WHEN '77' THEN '25'
WHEN '78' THEN '41'
WHEN '80' THEN '79'
WHEN '85' THEN '75'
WHEN '87' THEN '73'
WHEN '15' THEN '15'
WHEN '51' THEN '51'
WHEN '88' THEN '88'
WHEN '00' THEN '00'
WHEN '99' THEN '99'
WHEN '12' THEN DECODE(C.R_ID, 'N', '16','18')
ELSE 'NONE' END)
FROM D1.C C
WHERE EXISTS
(SELECT 1
FROM D1.SD A, D2.SDP B, D1.C C
WHERE A.SDN = B.DN
AND B.SDI = '000000'
AND B.PFI = 'W'
AND B.CID = C.CID
AND A.SDN = '0001500721');
END;Your parenthesis look a tad messed up ... think this fixes them.
CREATE OR REPLACE procedure NRI
IS
BEGIN
UPDATE IEB2 SET SDI =
SELECT
CASE PSDI
WHEN '11' THEN '16'
WHEN '13' THEN '38'
WHEN '14' THEN '18'
WHEN '23' THEN '21'
WHEN '24' THEN '21'
WHEN '31' THEN '27'
WHEN '32' THEN '37'
WHEN '33' THEN '38'
WHEN '34' THEN '37'
WHEN '43' THEN '46'
WHEN '53' THEN '45'
WHEN '55' THEN '48'
WHEN '60' THEN '54'
WHEN '61' THEN '57'
WHEN '62' THEN '54'
WHEN '63' THEN '56'
WHEN '64' THEN '52'
WHEN '70' THEN '21'
WHEN '77' THEN '25'
WHEN '78' THEN '41'
WHEN '80' THEN '79'
WHEN '85' THEN '75'
WHEN '87' THEN '73'
WHEN '15' THEN '15'
WHEN '51' THEN '51'
WHEN '88' THEN '88'
WHEN '00' THEN '00'
WHEN '99' THEN '99'
WHEN '12' THEN DECODE(C.R_ID, 'N', '16','18')
ELSE 'NONE'
END
FROM D1.C C
WHERE EXISTS
SELECT 1
FROM D1.SD A, D2.SDP B, D1.C C
WHERE A.SDN = B.DN
AND B.SDI = '000000'
AND B.PFI = 'W'
AND B.CID = C.CID
AND A.SDN = '0001500721'
END; -
Hi all,
I have two tables:
CRETE TABLE T1 (T1_COL1 NUMBER, T1_COL2 NUMBER)
CRETE TABLE T2 (T2_COL1 NUMBER, T2_COL2 NUMBER)
T1 may or may not have records. T2 always has records. There are two scenarios.
Scenario 1:
=======
SELECT * FROM T1 returns five rows, and SELECT * FROM T2 returns 10 rows.
Now I need the five rows from T1.
Scenario 2:
=======
SELECT * FROM T1 returns zero rows, and SELECT * FROM T2 returns 10 rows.
Now I need the 10 rows from T2.
In other words, if records present in T1, I need them all. If not, I need records from T2.
There are no common columns (for joins).
Now need a single query to achive this. I tried set operators, CASE and DECODE. But I'm unable to solve it.
Please help. Thanks in advance.Iniyavan wrote:
Yes, Justin. I'm sure that this is the way it's modelled. I also find it's tough and odd.Are you sure it's the right way for that data to be modeled? I understand that's the way it is being modeled, but a data model change may be the best option.
Is there any other way, which is simpler, without using RANK?That's the simplest option I can think of. You could also do something like
SELECT t1_col1, t1_col2
FROM (
SELECT t1_col1, t1_col2, rownum rn
FROM (
SELECT t1_col1, t1_col2
FROM (
SELECT t1_col1, t1_col2, 1 tbl
FROM t1
UNION ALL
SELECT t2_col2, t2_col2, 2 tbl
FROM t2
ORDER BY tbl
WHERE rn = 1I'm not sure that's any simpler...
Justin -
Unable to return a number from CASE statement in plsql
Hello all!
Back in November of last year, I received some assistance from user "jarola" regarding changing the color of a column item in a query based on the resulting value. This discussion yielded;
declare
l_query varchar2(4000) := '';
begin
l_query := '
select i.INVENTORY_ID,
io.ORDER_QUANTITY,
CASE
WHEN i.QUANTITY_AVAILABLE=0
THEN ''<span style="color:red;"> ''|| i.QUANTITY_AVAILABLE ||''</span>''
ELSE to_char(i.QUANTITY_AVAILABLE)
END,
i.QUANTITY_AVAILABLE qty_avail_hold,
i.STRAIN_CODE,
i.STRAIN_NAME,
i.GENOTYPE,
i.AGE,
i.***,
(lower(substr(i.ROOM_NUMBER,1,instr(i.ROOM_NUMBER,''-'',1,1)-1))) ROOM_NUMBER
from SM_INVENTORY i,
SM_INVENTORY_ORDER io
where io.ORDER_ID (+)= :F111_MODIFYING_ORDER
and io.INVENTORY_ID (+)= i.INVENTORY_ID';
return l_query;
end;Problem is, sorting (report attributes for column set to "sort") on column i.QUANTITY_AVAILABLE is broken as even though the data in the table is number(12,0), the CASE statement returns it as alpha. I'm having difficulty getting this CASE statement to return a number as these modifications cause generic compilation errors.
ELSE i.QUANTITY_AVAILABLE
ELSE to_number(i.QUANTITY_AVAILABLE)
Google/sqlplus docs have yielded little. Might anyone offer advice?
Thanks!!!
PaulHello Varad! Thanks for the reply.
Sorry, but I copied some old information in my code example. the CASE statement I'm actually using is;
CASE
WHEN i.QUANTITY_AVAILABLE=0
THEN ''<span style="color:red;"> ''|| i.QUANTITY_AVAILABLE ||''</span>''
ELSE to_char(i.QUANTITY_AVAILABLE)
END AS QUANTITY_AVAILABLESo I'm already returning the result as labeled "QUANTITY_AVAILABLE".
What I did was click on the pencil/paper icon to the left of the alias of my column in the "Column Attributes" pane in "Report Attributes" to get to the "Column Attributes" page and plugged #QUANTITY_AVAILABLE# into the HTML Expression field of the "Column Formatting" pane of the "Column Attributes" page for the "QUANTITY_AVAILABLE" column.
No joy, sort still broken...
Isn't the problem that fundamentally, the CASE statement returns an alpha? I wouldn't expect the sort to ever work until it can return a number (which it appears SQL, used this way, it cannot do).
So, I considered that END AS QUANTITY_AVAILABLE might be the problem as it's named the same as the column, so I changed it (and the HTML Expression entry) to END AS QUANTITY_AVAIL (changed the name).
Sort as alpha still happening.
Any other thoughts? -
Dear All,
Im having the table like
the following,
i need ther report like if i give role ,region and segment mean then i need onmenuid 2 alone.
if input is role and region alone the i need those combinations result alone .
if the input is role alone thatn i need that combinations menu id.
MENUID ROLE REGION SEGMENT
13
27 Account Manager
29 Account Manager
1 Account Manager
2 Account Manager SOUTH
2 COO EAST Corporate
Thanks In Advance,
839083You posted in wrong forum.
Please post at PL/SQL
Hope this helps..
If someone's response is helpful or correct, please mark it accordingly. -
CASE STATEMENTS AND CASE EXPRESSIONS IN ORACLE9I PL/SQL
제품 : PL/SQL
작성날짜 : 2001-11-13
CASE STATEMENTS AND CASE EXPRESSIONS IN ORACLE9I PL/SQL
=======================================================
PURPOSE
아래의 자료는 Case 문에서 oracle 8.1.7과 Oracle 9i의 New Feature로 8.1.7에서는
sqlplus 에서만 가능했고, 9i 부터는 pl/sql 까지 가능하다.
Explanation
1. Oracle 8.1.7 Feature
Oracle 8.1.7 에서 Case 문은 Decode 문과 유사하지만, 기존의 decode 문을 쓰는 것보다
더 많은 확장성과 Logical Power와 좋은 성능을 제공한다. 주로 나이와 같이 category 별로
나눌때 주로 사용하고 Syntex는 아래와 같다.
CASE WHEN <cond1> THEN <v1> WHEN <cond2> THEN <v2> ... [ELSE <vn+1> ] END
각각의 WHEN...THEN 절의 argument 는 255 까지 가능하고 이 Limit를 해결하려면
Oracle 8i Reference를 참조하면 된다.
The maximum number of arguments in a CASE expression is 255, and each
WHEN ... THEN pair counts as two arguments. To avoid exceeding the limit of 128 choices,
you can nest CASE expressions. That is expr1 can itself be a CASE expression.
Case Example : 한 회사의 모든 종업원의 평균 봉급을 계산하는데 봉급이 $2000보다 작은경우
2000으로 계산을 하는 방법이 pl/sql을 대신하여 case function을 사용할 수 있다.
SELECT AVG(CASE when e.sal > 2000 THEN e.sal ELSE 2000 end) FROM emp e;
Case Example : 나이를 column으로 가지고 있는 customer table을 예로 들어보자.
SQL> SELECT
2 SUM(CASE WHEN age BETWEEN 70 AND 79 THEN 1 ELSE 0 END) as "70-79",
3 SUM(CASE WHEN age BETWEEN 80 AND 89 THEN 1 ELSE 0 END) as "80-89",
4 SUM(CASE WHEN age BETWEEN 90 AND 99 THEN 1 ELSE 0 END) as "90-99",
5 SUM(CASE WHEN age > 99 THEN 1 ELSE 0 END) as "100+"
6 FROM customer;
70-79 80-89 90-99 100+
4 2 3 1
1 SELECT
2 (CASE WHEN age BETWEEN 70 AND 79 THEN '70-79'
3 WHEN age BETWEEN 80 and 89 THEN '80-89'
4 WHEN age BETWEEN 90 and 99 THEN '90-99'
5 WHEN age > 99 THEN '100+' END) as age_group,
6 COUNT(*) as age_count
7 FROM customer
8 GROUP BY
9 (CASE WHEN age BETWEEN 70 AND 79 THEN '70-79'
10 WHEN age BETWEEN 80 and 89 THEN '80-89'
11 WHEN age BETWEEN 90 and 99 THEN '90-99'
12* WHEN age > 99 THEN '100+' END)
SQL> /
AGE_G AGE_COUNT
100+ 1
70-79 4
80-89 2
90-99 3
Example
2. Oracle 9i Feature
Oracle 9i부터는 pl/sql에서도 case문을 사용할 수 있으면 이것은
복잡한 if-else 구문을 없애고, C언어의 switch문과 같은 기능을 한다.
아래의 9i pl/sql Sample 및 제약 사항을 보면 아래와 같다.
Sample 1:
A simple example demonstrating the proper syntax for a case
statement
using a character variable as the selector. See the section entitled
'Restrictions' at the end of this article for details on which PLSQL
datatypes may appear as a selector in a case statement or
expression.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
begin
case achar
when 'A' then dbms_output.put_line('The description was Excellent');
when 'B' then dbms_output.put_line('The description was Very Good');
when 'C' then dbms_output.put_line('The description was Good');
when 'D' then dbms_output.put_line('The description was Fair');
when 'F' then dbms_output.put_line('The description was Poor');
else dbms_output.put_line('The description was No such Grade');
end case;
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 2:
A simple example demonstrating the proper syntax for a case
expression
using a character variable as the selector. See the section entitled
'Restrictions' at the end of this article for details on which PLSQL
datatypes may appear as a selector in a case statement or
expression.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
description varchar2(20);
begin
description :=
case achar
when 'A' then 'Excellent'
when 'B' then 'Very Good'
when 'C' then 'Good'
when 'D' then 'Fair'
when 'F' then 'Poor'
else 'No such grade'
end;
dbms_output.put_line('The description was ' || description);
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
NOTE: The above simple samples demonstrate two subtle differences in the
syntax
required for case statements and expressions.
1) A case STATEMENT is terminated using the 'end case' keywords; a
case
EXPRESSION is terminated using only the 'end' keyword.
2) Each item in a case STATEMENT consists of one or more
statements, each
terminated by a semicolon. Each item in a case expression
consists of
exactly one expression, not terminated by a semicolon.
Sample 3:
Sample 1 demonstrates a simple case statement in which the selector
is
compared for equality with each item in the case statement body.
PL/SQL
also provides a 'searched' case statement as an alternative; rather
than
providing a selector and a list of values, each item in the body of
the
case statement provides its own predicate. This predicate can be any
valid boolean expression, but only one case will be selected.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
begin
case
when achar = 'A' then dbms_output.put_line('The description was
Excellent');
when achar = 'B' then dbms_output.put_line('The description was Very
Good');
when achar = 'C' then dbms_output.put_line('The description was
Good');
when achar = 'D' then dbms_output.put_line('The description was
Fair');
when achar = 'F' then dbms_output.put_line('The description was
Poor');
else dbms_output.put_line('The description was No such Grade');
end case;
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 4:
This sample demonstrates the proper syntax for a case expression of
the
type discussed in Sample 3 above.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
description varchar2(20);
begin
description :=
case
when achar = 'A' then 'Excellent'
when achar = 'B' then 'Very Good'
when achar = 'C' then 'Good'
when achar = 'D' then 'Fair'
when achar = 'F' then 'Poor'
else 'No such grade'
end;
dbms_output.put_line('The description was ' || description);
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 5:
This sample demonstrates the use of nested case statements. It is
also
permissable to nest case expressions within a case statement (though
it
is not demonstrated here), but nesting of case statements within a
case
expression is not possible since statements do not return any value.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
anum1 number := &anum1;
anum2 number := &anum2;
answer number;
begin
case anum1
when 1 then case anum2
when 1 then answer := 10;
when 2 then answer := 20;
when 3 then answer := 30;
else answer := 999;
end case;
when 2 then case anum2
when 1 then answer := 15;
when 2 then answer := 25;
when 3 then answer := 35;
else answer := 777;
end case;
else answer := 555;
end case;
dbms_output.put_line('The answer is ' || answer);
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 6:
This sample demonstrates nesting of case expressions within another
case
expression. Note again the absence of semicolons to terminate both
the
nested case expression and the individual cases of those
expressions.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
declare
anum1 number := &anum1;
anum2 number := &anum2;
answer number;
begin
answer :=
case anum1
when 1 then case anum2
when 1 then 10
when 2 then 20
when 3 then 30
else 999
end
when 2 then case anum2
when 1 then 15
when 2 then 25
when 3 then 35
else 777
end
else 555
end;
dbms_output.put_line('The answer is ' || answer);
end;
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Although PL/SQL anonymous blocks have been used in all of the examples
so far,
case statements and expressions can also be used in procedures,
functions, and
packages with no changes to the syntax.
The following samples are included for completeness and demonstrate the
use of
case statements and/or expressions in each of these scenarios.
Sample 7:
This sample demonstrates use of a case statement in a stored
procedure.
Note that this sample also demonstrates that it is possible for each
of
the items in the case body to consist of more than one statement.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
create or replace procedure testcasestmt ( anum IN number ) is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
end;
exec testcasestmt(&anum);
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 8:
This sample demonstrates the use of a case statement in a stored
package.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
create or replace package testpkg2 is
procedure testcasestmt ( anum IN number );
function testcasestmt_f ( anum IN number ) return number;
end testpkg2;
create or replace package body testpkg2 is
procedure testcasestmt ( anum IN number ) is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
end;
function testcasestmt_f ( anum IN number ) return number is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
return anum;
end;
end testpkg2;
exec testpkg2.testcasestmt(&anum);
variable numout number
exec :numout := testpkg2.testcasestmt_f(&anum);
print numout
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
Sample 9:
This sample demonstrates the use of a case expression in a stored
package.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
set serveroutput on
create or replace package testpkg is
procedure testcase ( anum IN number );
function testcase_f ( anum IN number ) return number;
end testpkg;
create or replace package body testpkg is
procedure testcase ( anum IN number ) is
anumber number := anum;
anothernum number;
begin
anothernum :=
case
when anumber = 1 then anumber + 1
when anumber = 2 then anumber + 2
when anumber = 3 then anumber + 3
when anumber = 4 then anumber + 4
when anumber = 5 then anumber + 5
else 999
end;
dbms_output.put_line('The number was ' || anothernum);
end;
function testcase_f ( anum IN number ) return number is
anumber number := anum;
anothernum number;
begin
anothernum :=
case
when anumber = 1 then anumber + 1
when anumber = 2 then anumber + 2
when anumber = 3 then anumber + 3
when anumber = 4 then anumber + 4
when anumber = 5 then anumber + 5
else 999
end;
dbms_output.put_line('The number was ' || anothernum);
return anothernum;
end;
end testpkg;
variable numout number
exec testpkg.testcase(&anum);
exec :numout := testpkg.testcase_f(&anum);
print numout
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
제약 사항
다음의 databasetype은 case 문에서 지원되지 않는다.
BLOB
BFILE
VARRAY
Nested Table
PL/SQL Record
PL/SQL Version 2 tables (index by tables)
Object type (user-defined type)
All of these types except for object types face a similar restriction
even for if statements (i.e. they cannot be compared for equality directly) so this is unlikely to change for these types. Lack of support for object types is simply an implementation restriction which may be relaxed in future releases.
Reference Ducumment
Oracle 8.1.7 Manual
NOTE:131557.1I have done the following code but doesn't
like the statement of - "case(butNext)". What do you mean "doesn't like" -- did you get an error message?
I'm guessing it won't compile because you're trying to switch on a Button.
I tried something
like "g.fillOval(100,50,70,90, BorderLayout.NORTH)"...no that doesn't make sense. You only use BorderLayout.NORTH when you're adding components to a BorderLayout layout manager. An oval is not a component and fillOval isn't adding a component and Graphics is not a Panel or layout manager.
Would appreciate it if someone could tell me how to position
shapes using the graohic method. I think the problem is that you're confusing shapes with components. -
In Line CASE Statement OR Function
Hi Gurus,
What approach do you typically take in queries where you need to run CASE/DECODE type logic on a query? Obviously for small logic sets DECODE or CASE is fine in the query, but when I have to run a lot of logic for a column output I tend to prefer the FUNCTION. The problem with that approach is the performance. I have read about Function Based Indexes, but they seem to be more for FUNCTIONS that would go against a Single table (i.e. UPPER(CustomerName)).
I would greatly appreciate any info/comments about how to approach this. What I am finding is that in my initial phases of a project my current query(s) are fine, but then as time passes more and more logic needs to be applied and my CASE/DECODES become very hard to maintain.
Thanks,
SYou are correct they are user defined functions. I will take a look at the link you provided....thanks for the info.
Your statement about he data model is what is basiclaly the problem. I have to look at all kind of identifiers, values to determine things like Shipping Rates, Pricing, Qty, etc. What started out as not being that bad has turned into a real headache to try and maintain the logic.
I was trying to implement some user defined FUNCTIONs to break the logic out of the base queries thinking that would help make the code more maintainable, but have started to encounter some performance issues.
--S -
Decoding- best way to decode characters to numbers using a conversion table
I have input string which mostly contains numbers, but at the end there are 2 characters which means a country code, like 'EE' for estonia, or 'LV' for latvia and so on, see example input value:
select '9999123456789012EE00' input, null output from dual;I want into column Output to put value where those 2 characters are decoded/replaced with numbers with following algorithm:
1. replace in input string 9999123456789012EE00 characters with numbers 14 and 14 so the output would be 9999123456789012141400.
2. The 14 was for specially letter 'E', all alphabet is encoded like following:
A=10
B=11
C=12
D=13
E=14
Y=34
Z=35
So, value "9999123456789012LV00" should be converted into 9999123456789012213100 (L = 21, V =31).
What is the best way to achieve such decoding in plsql/sql?
Edited by: CharlesRoos on Mar 16, 2010 3:52 AMThx, Seems very nice.
with t as (
select '9999123456789012LV00' input from dual
union all
select '9999123456789012AA00' input from dual
union all
select '9AA99912345678901200' input from dual
select input,
regexp_replace (input, '[[:alpha:]]+',
(ascii (regexp_substr (input, '[[:alpha:]]')) - 55) || (ascii (regexp_substr (input, '[[:alpha:]]',1,2)) - 55))output
from t
9999123456789012LV00 9999123456789012213100
9999123456789012AA00 9999123456789012101000
9AA99912345678901200 9101099912345678901200
; -
Problem with OWB Paris (case expression)
I've got a little problem with defining an attribute property. I've defined a simple case statement: case when LKP_IN.TEST_TAB_ID is null then 'INS' else 'UPD' end. When I validate the expression I get the following error message:
Line 1, Col 8:
PLS-00103: Encountered the symbol "when" when expecting one of the following:
. ( * @ % & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_
LIKE4_ LIKEC_ between || multiset member SUBMULTISET_
The symbol ". was inserted before "when" to continue.
Line 1, Col 50:
PLS-00103: Encountered the symbol "THEN" when expecting one of the following:
; and or
Needless to say that this worked well with OWB 10g R1. Any clue?
Thanks in advance
JörgHello, Jörg
To what database are you trying to deploy your mapping? It seems that db version is pre-9i?
If so, note that CASE statement is unavailable in PL/SQL until Oracle 9i its available only in SQL (in pre-9i Oracle had different code from SQL and PL/SQL interpretation, after 9i it share interpreter code). The compilation error may appear in ROW-based parts of package: OWB generates code that calls CASE statement directly in PL/SQL it cause error.
To avoid deployment error wrap this expression component by some operator (order, dedup, join, set). In this case OWB pack expression along with wrap operator in SQL statement and package will compile.
Where were discussion here (in forum) about using analytical function in mapping the same approach works for CASE / DECODE if deploying to pre-9i database.
Sergey -
Difference between Oracle 8i and 9i
Hi,
Can anyone suggest me what's the difference ( in sql and pl/sql) between Oracle 8i and 9i versions ???
What's the main feature of PL/SQL in Oracle 10g ???
RegardsHi,
In SQL 9i there are lot of new syntaxes included.
with 9i
1) Scaler subqueries were included(in order by clause and SELECt clause
2) TimeStamp data type(WITH/WITNOUT TIMEZONE) introduced and along with other relevant date conversion functions introduced
3) WITH clause introduced for storing the subqueries temporarily in the session
3) MERGE statement is one more new DML introduced in 9i
4) Few functions introduced in 9i such as NVL2,COALACE,CASE, DECODe etc.
5) Few more join types introduced, with some new keywords like USING, ON etc. also new Join Syntax introduced compatible with ANSI SQL 1999 standards
also FULL OUTER JOIN made easier without using UNION clauses.
6) iSQL Plus introduced that is a GUI version of CUI SQL PLUS
7) For the grouping mechanism, GROUPING and GROUPING SETS are 2 new functiosn introduced.
8) Multitable INSERT statements for different purposes other than normal OLTP work.
9) Enhancements in PLSQL, EXECUTE IMMEDIATE
10) Few more Oracle Supplied Packages made available.
11) ALTER TABLE syntax for changin LONG column to LOB introduced.
I have tried to put here whatever i cud remember with the help of my notebooks and docs.
Thanks
Regards
Abhivyakti
Maybe you are looking for
-
Oracle 9i monitoring scripts in HACMP 5.4
Hi, I have installed Oracle 9.2.0.8 on AIX 5.3 (HACMP 5.4) in active passive cluster. I have made startup and shutdown scripts for Oracle. Can anyone please guide me or point me to some link for the monitoring scripts for Oracle in HACMP so that fail
-
Standard Business Content - Loan Management & Term Deposit
Hi ALL, I would like to does anyone has used Business Content Cubes on Loan Management & Term Deposit and its report, please advise me which cube appropriate Thanks BR Nathan
-
[SOLVED] Need help with simple a script.
Hello, Iam searching for a small script that sorts my folders in alphabetical order. I want the script to create folder from A to Z and then move every folder that begins with A into the A folder etc etc.. I really hope anyone understands what im sea
-
Hi guys, excuse me if i repeat a my old post,but now i have more clear ideas about problems. I've developed an authorization filter in my jsf application that when a page is loaded try to find a visit object in the session,if it doesn't find show log
-
CONVERSION_FACTOR_GET
Hi, I am trying to same meter reading in transaction EL28 by giving a contract Number. After Pressing Save button it is giving a message ' Unit of Measure M3 can not be converted into ******'. and also it is advising to look into the above functio