1. A column has some
negative values and some positive values. It is required to find the sum of
negative numbers and the sum of the positive numbers in two separate columns.
1
2
3
4
5
6
7
8
9
10
|
create table neg_pos(num
number);
insert into neg_pos
values(-1);
insert into neg_pos
values(-2);
insert into neg_pos
values(-3);
insert into neg_pos
values(-4);
insert into neg_pos
values(1);
insert into neg_pos
values(2);
insert into neg_pos
values(3);
insert into neg_pos
values(4);
commit;
|
1
2
3
4
5
6
7
8
9
10
|
select *
from neg_pos ;
num
-1
-2
-3
-4
1
2
3
4
|
Answer :
1
2
3
4
|
SELECT
SUM(CASE WHEN num
< 0 THEN num ELSE 0 END) neg,
SUM(CASE WHEN num
> 0 THEN num ELSE 0 END)pos
FROM neg_pos;
|
gives
————-
neg | pos
————-
-10 | 10
————-
————-
neg | pos
————-
-10 | 10
————-
****************************************************
2. How to search for
strings containing ‘%’ in Oracle? Search for columns containing ‘%’ in Oracle.
In ORACLE , you can use the ESCAPE keyword to search for strings containing ‘%’. Otherwise it would be considered as a META CHARACTER .
In ORACLE , you can use the ESCAPE keyword to search for strings containing ‘%’. Otherwise it would be considered as a META CHARACTER .
Using the escape
character ( to search for strings containing like ‘ABC %%TRF’, ‘TR%FF’ or
‘%GH’)
Answer :
1
2
|
SELECT col_name
FROM tbl_name
WHERE col_name
LIKE '%?%%' ESCAPE '?';
|
Here ‘?’ can be replaced
with any other character.
Another solution:
Another solution:
1
2
|
SELECT col_name
FROM tbl_name
WHERE instr(col_name,'%')
> 0
|
****************************************************
3. How does one remove
special characters in ORACLE?
To replace special
characters in a string with null use translate :
translate(‘string’,'to_replace’,'replace_with’)
translate(‘string’,'to_replace’,'replace_with’)
for eg:
1
2
|
SELECT translate
('asdfsd@#@$#$%$sdfg&;','!@#$%^&;*()_+=-`~?><: from="" span=""> dual;
|
will return—asdfsdsdfg
To remove quotes, use two quotes for every single quote as shown
below:
1
2
3
4
|
CREATE TABLE test_quote(quote
VARCHAR2(5));
INSERT INTO test_quote
VALUES ('L''uck');
SELECT *
FROM test_quote;
SELECT REPLACE(quote,'''','')
from test_quote;
|
A table has columns with numbers and numbers with alphabets.
Write a query to select only those rows which contains alphanumeric values.
1
2
3
4
5
6
7
8
|
create table alpha_numeric(col1
varchar2(20));
insert into alpha_numberic
values ('1000');
insert into alpha_numberic
values ('a1093b');
insert into alpha_numberic
values ('19b45');
insert into alpha_numberic
values ('231');
insert into alpha_numberic
values ('1000cc');
insert into alpha_numberic
values ('a1000');
commit;
|
Answer:
1
2
|
SELECT *
from alpha_numeric
where length(trim(translate(col1,'1234567890','
'))>0);
|
col1
——
a1093b
19b45
1000cc
a1000
——
a1093b
19b45
1000cc
a1000
****************************************************
4. Give a string of
format ‘NN/NN’, verify that the first and last two characters are numbers and
that the middle character is’/’. Print the expression ‘NUMBER’ if valid, ‘NOT
NUM’ if not valid. Use the following values to test your solution.
‘12/34’,’01/1a’, ‘99/98’.
Answer:
1
2
3
4
5
6
|
SELECT CASE WHEN ascii(substr('99/98',1,1))
BETWEEN 48 AND 57
AND ascii(substr('99/98',2,1))
BETWEEN 48 AND 57
AND substr('99/98',3,1)
='/'
AND ascii(substr('99/98',4,1))
BETWEEN 48 AND 57
AND ascii(substr('99/98',5,1))
BETWEEN 48 AND 57
THEN 'number' ELSE 'not
num' END FROM dual;
|
****************************************************
5. From the given table,
find those employees who are more than 21 years of age.
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE find_age(NAME Varchar2(10),
dob DATE);
INSERT INTO find_age
VALUES('AAA',to_date('06/02/1983','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('BBB',to_date('06/02/1967','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('CCC',to_date('02/06/1983','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('DDD',to_date('03/06/1983','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('EEE',to_date('04/06/1999','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('FFF',to_date('04/06/1999','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('GGG',to_date('02/06/1999','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('HHH',to_date('02/06/1990','DD/MM/YYYY'));
INSERT INTO find_age
VALUES('III',to_date('03/06/1990','DD/MM/YYYY'));
COMMIT;
|
Answer:
1
2
|
SELECT NAME FROM find_age
WHERE dob
>(SELECT add_months(SYSDATE,-(12*21)) FROM dual);
|
****************************************************
6. There are two tables
stu_dept and dept_cap. stu_dept contains the student name and the
department(consider distinct values). dept_cap contains the capacity for each
department. We need to find those departments(DEPT) where the number of
students is less than the total capacity of the department.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
CREATE TABLE stu_dept(stu_name
VARCHAR2(30), dept VARCHAR2(30));
INSERT INTO stu_dept
VALUES('AAA','D1');
INSERT INTO stu_dept
VALUES('BBB','D1');
INSERT INTO stu_dept
VALUES('CCC','D1');
INSERT INTO stu_dept
VALUES('DDD','D1');
INSERT INTO stu_dept
VALUES('EEE','D2');
INSERT INTO stu_dept
VALUES('FFF','D2');
INSERT INTO stu_dept
VALUES('GGG','D2');
INSERT INTO stu_dept
VALUES('HHH','D3');
INSERT INTO stu_dept
VALUES('III','D3');
INSERT INTO stu_dept
VALUES('JJJ','D3');
INSERT INTO stu_dept
VALUES('KKK','D3');
INSERT INTO stu_dept
VALUES('LLL','D3');
CREATE TABLE dept_cap(dept
VARCHAR2(5),capacity NUMBER);
INSERT INTO dept_cap
VALUES('D1',5);
INSERT INTO dept_cap
VALUES('D2',5);
INSERT INTO dept_cap
VALUES('D3',5);
|
Answer:
1
2
3
4
5
6
|
SELECT a.dept,a.capacity-t.cap
remaining_seats
FROM dept_cap
a,
(SELECT dept,COUNT(dept)cap
FROM stu_dept
GROUP BY dept)t
WHERE a.dept=t.dept
|
****************************************************
7. Some questions on the
dual table.
Select two rows from dual
1
2
3
|
select dummy
from dual
union all
select dummy
from dual
|
To dispaly the numbers 1..10 from dual
1
2
|
select level from dual
connect by level <=10
|
or
1
2
|
SELECT ROWNUM
FROM dual
CONNECT BY ROWNUM
<=10
|
Another tricky question
on dual involves the use of decode with NULL.
1
|
SELECT decode(null,null,1,0)
from dual;
|
OUTPUT—1
Although two NULL values are not equal, the output is 1, as decode checks for the existence of NULL and does not compare the two values.
Although two NULL values are not equal, the output is 1, as decode checks for the existence of NULL and does not compare the two values.
****************************************************
8. Find the missing
sequence. Table test_number contains the sequence for each id. Table
test_number_min_max contains the minimum and maximum number for each id. We
need to find the missing number between the minimum and maximum number for each
id. text column can be ignored.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
CREATE TABLE test_number(id
NUMBER,SEQ NUMBER,text VARCHAR2(5)) ;
INSERT INTO test_number
VALUES(1,1,'AA');
INSERT INTO test_number
VALUES(1,3,'CC');
INSERT INTO test_number
VALUES(1,4,'DD');
INSERT INTO test_number
VALUES(1,5,'EE');
INSERT INTO test_number
VALUES(1,6,'FF');
INSERT INTO test_number
VALUES(1,7,'GG');
INSERT INTO test_number
VALUES(1,8,'HH');
INSERT INTO test_number
VALUES(1,10,'JJ');
INSERT INTO test_number
VALUES(2,1,'KK');
INSERT INTO test_number
VALUES(2,2,'LL');
INSERT INTO test_number
VALUES(2,3,'MM');
INSERT INTO test_number
VALUES(2,4,'NN');
INSERT INTO test_number
VALUES(2,6,'PP');
INSERT INTO test_number
VALUES(2,7,'QQ');
INSERT INTO test_number
VALUES(3,1,'TT');
INSERT INTO test_number
VALUES(3,4,'ZZ');
INSERT INTO test_number
VALUES(3,5,'XX');
create tabel
test_number_min_max(id number,mn number,mx number);
INSERT INTO test_number_min_max
VALUES(1,1,12);
INSERT INTO test_number_min_max
VALUES(2,1,9);
INSERT INTO test_number_min_max
VALUES(3,1,5);
|
Answer:
1
2
3
4
5
6
7
8
|
SELECT r
id,rn seq FROM (SELECT ROWNUM rn FROM all_objects
WHERE ROWNUM <13 span="">
(SELECT ROWNUM
r FROM all_objects
WHERE ROWNUM
<4 m="" span="" test_number_min_max="">
WHERE r=id
AND rn
>= mn
AND rn
<= mx
AND (r,rn)
NOT IN
(SELECT id,seq
FROM test_number)
|
OR
1
2
3
4
5
6
7
8
9
|
SELECT r
id ,l seq FROM
(SELECT LEVEL l
FROM dual
CONNECT BY LEVEL <13 span="">
(SELECT LEVEL r
FROM dual CONNECT
BY LEVEL <4 span="">
test_number_min_max
WHERE r=id
AND l>=mn
AND l<=mx
AND (r,l)
NOT IN (SELECT id,seq FROM test_number)
|
OUTPUT :
ID SEQ
1 2
1 9
1 11
1 12
2 5
2 8
2 9
3 2
3 3
ID SEQ
1 2
1 9
1 11
1 12
2 5
2 8
2 9
3 2
3 3
****************************************************
9. Get the following
OUTPUT using dual
1 L R
—————
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
1 L R
—————
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
Answer:
1
2
3
4
|
SELECT *
FROM
(SELECT 1
FROM dual),
(SELECT LEVEL l
FROM dual CONNECT
BY LEVEL <4 span="">
(SELECT LEVEL r
FROM dual CONNECT
BY LEVEL <4 span="">
|
****************************************************
10. Check the Input and
Output and try to figure out the question.
1
2
3
4
5
6
7
|
CREATE TABLE test_output(NAME VARCHAR2(5),
city VARCHAR2(6), num NUMBER);
INSERT INTO test_output
VALUES ('AN','TTT',5);
INSERT INTO test_output
VALUES ('AN','TTT',6);
INSERT INTO test_output
VALUES ('AN','TTT',7);
INSERT INTO test_output
VALUES ('BB','RRR',8);
INSERT INTO test_output
VALUES ('BB','RRR',9);
INSERT INTO test_output
VALUES ('BB','RRR',10);
|
Input :
NAME
|
CITY
|
NUM
|
AN
|
TTT
|
5
|
AN
|
TTT
|
6
|
AN
|
TTT
|
7
|
BB
|
RRR
|
8
|
BB
|
RRR
|
9
|
BB
|
RRR
|
10
|
Answer :
1
2
3
4
5
6
7
|
SELECT (CASE WHEN rn=1
THEN NAME ELSE NULL END) NAME,
(CASE WHEN rn=1
THEN CITY ELSE NULL
END )
CITY,
num
FROM
(SELECT NAME,city,num,
row_number()
over(PARTITION BY NAME,city ORDER
BY NAME)
rn
FROM test_output);
|
Output :
NAME
|
CITY
|
NUM
|
AN
|
TTT
|
5
|
6
|
||
7
|
||
BB
|
RRR
|
8
|
9
|
||
10
|
****************************************************
11.
****************************************************
12. Beginner question
based on the above logic. From the table given below, all the numbers should be
on the first column and the alphabets on the second column.
ALPA RANK
———-
a 1
b 2
c 4
x 5
y 6
z 8
9 g
0 f
7 e
3 d
———-
a 1
b 2
c 4
x 5
y 6
z 8
9 g
0 f
7 e
3 d
All the alphabets on
column B and all numbers in column A
OUTPUT:
A B
——–
0 f
1 a
2 b
3 d
4 c
5 x
6 y
7 e
8 z
9 g
OUTPUT:
A B
——–
0 f
1 a
2 b
3 d
4 c
5 x
6 y
7 e
8 z
9 g
Answer:
1
2
|
SELECT least(alpa,rank)
a,greatest(alpa,rank) b FROM test_b
ORDER BY 1
|
****************************************************
13. One of the most common
question asked in interviews. To find the second (or third or fourth…) nth
highest number in each group.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
CREATE TABLE find_rank(group_id
VARCHAR2(2),val NUMBER);
INSERT INTO find_rank
VALUES ('G1',11);
INSERT INTO find_rank
VALUES ('G1',12);
INSERT INTO find_rank
VALUES ('G1',13);
INSERT INTO find_rank
VALUES ('G1',14);
INSERT INTO find_rank
VALUES ('G2',8);
INSERT INTO find_rank
VALUES ('G2',10);
INSERT INTO find_rank
VALUES ('G2',10);
INSERT INTO find_rank
VALUES ('G2',19);
INSERT INTO find_rank
VALUES ('G2',21);
INSERT INTO find_rank
VALUES ('G3',1);
INSERT INTO find_rank
VALUES ('G3',2);
INSERT INTO find_rank
VALUES ('G3',4);
INSERT INTO find_rank
VALUES ('G4',0);
INSERT INTO find_rank
VALUES ('G5',-1);
INSERT INTO find_rank
VALUES ('G5',-2);
INSERT INTO find_rank
VALUES ('G5',-3);
COMMIT;
|
Answer:
1
2
3
4
5
6
|
SELECT DISTINCT *
FROM
(SELECT group_id,val,
dense_rank() over
(PARTITION BY group_id
ORDER BY val DESC) rn
FROM find_rank)
t
WHERE t.rn=&rank
|
with &rank = 2
GROUP_ID VAL RN
———————-
G1 13 2
G2 19 2
G3 2 2
G5 -2 2
———————-
G1 13 2
G2 19 2
G3 2 2
G5 -2 2
If we need to have G4
also in the output even though it does not have a second/third highest value
then :
1
2
3
4
5
6
7
8
9
10
|
SELECT DISTINCT f.group_id,
CASE WHEN o.val
> 0 THEN to_char(o.val) ELSE
'N/A' END val
FROM find_rank
f
LEFT OUTER JOIN
(SELECT DISTINCT group_id,val
FROM
(SELECT group_id,val,
dense_rank() over
(PARTITION BY group_id ORDER
BY val
DESC) rn
FROM find_rank)
t
WHERE t.rn=&rank)o
ON f.group_id=o.group_id
|
with &rank =3
GROUP_ID VAL
——————-
G1 12
G2 10
G3 1
G4 N/A
G5 -3
——————-
G1 12
G2 10
G3 1
G4 N/A
G5 -3
****************************************************
14. Another common
interview question. To transform column into rows.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
CREATE TABLE col_to_rows(stu_name
VARCHAR2(30),
subject
VARCHAR2(10),marks NUMBER);
INSERT INTO col_to_rows
VALUES('GEORGE','ECO',77);
INSERT INTO col_to_rows
VALUES('GEORGE','HIS',99);
INSERT INTO col_to_rows
VALUES('GEORGE','MAT',64);
INSERT INTO col_to_rows
VALUES('GEORGE','GEO',85);
INSERT INTO col_to_rows
VALUES('GEORGE','SCI',98);
INSERT INTO col_to_rows
VALUES('ROBERT','ECO',71);
INSERT INTO col_to_rows
VALUES('ROBERT','HIS',90);
INSERT INTO col_to_rows
VALUES('ROBERT','MAT',84);
INSERT INTO col_to_rows
VALUES('ROBERT','GEO',95);
INSERT INTO col_to_rows
VALUES('ROBERT','SCI',58);
INSERT INTO col_to_rows
VALUES('TIMOTHY','ECO',56);
INSERT INTO col_to_rows
VALUES('TIMOTHY','HIS',55);
INSERT INTO col_to_rows
VALUES('TIMOTHY','MAT',67);
INSERT INTO col_to_rows
VALUES('TIMOTHY','GEO',54);
INSERT INTO col_to_rows
VALUES('TIMOTHY','SCI',45);
COMMIT;
|
Answer :
1
2
3
4
5
6
7
8
|
SELECT stu_name,
max(CASE WHEN subject='ECO' THEN marks
ELSE 0 END) ECO,
max(CASE WHEN subject='HIS' THEN marks
ELSE 0 END) HIS,
max(CASE WHEN subject='MAT' THEN marks
ELSE 0 END) MAT,
max(CASE WHEN subject='GEO' THEN marks
ELSE 0 END) GEO,
max(CASE WHEN subject='SCI' THEN marks
ELSE 0 END) SCI
FROM col_to_rows
GROUP BY stu_name
|
OR
1
2
3
4
5
6
7
|
SELECT stu_name,
MAX(decode(subject,'ECO',marks,0))
ECO,
MAX(decode(subject,'HIS',marks,0))
HIS,
MAX(decode(subject,'MAT',marks,0))
MAT,
MAX(decode(subject,'GEO',marks,0))
GEO,
MAX(decode(subject,'SCI',marks,0))
SCI
FROM col_to_rows
GROUP BY stu_name
|
OR
1
2
3
4
5
6
7
8
|
SELECT stu_name,
max(CASE WHEN rn=1
THEN marks ELSE 0 END) ECO,
max(CASE WHEN rn=2
THEN marks ELSE 0 END) GEO,
max(CASE WHEN rn=3
THEN marks ELSE 0 END) HIS,
max(CASE WHEN rn=4
THEN marks ELSE 0 END) MAT,
max(CASE WHEN rn=5
THEN marks ELSE 0 END) SCI FROM
(SELECT stu_name,subject,marks,
rank() over (PARTITION BY stu_name ORDER BY subject
)rn FROM col_to_rows)
GROUP BY stu_name
|
Output :
STU_NAME
|
ECO
|
HIS
|
MAT
|
GEO
|
SCI
|
GEORGE
|
77
|
99
|
64
|
85
|
98
|
ROBERT
|
71
|
90
|
84
|
95
|
58
|
TIMOTHY
|
56
|
55
|
67
|
54
|
45
|
****************************************************
15. Another question from
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:65356113852721
. This question teaches the trick to use decode with order by to select your
own ordering rule . In this case the minimum value should always be at the last
row. The other values are sorted in ascending order. You can create your own
ordering rules.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
SQL> CREATE TABLE TEST1
(c1 NUMBER(2));
Table created
SQL> INSERT INTO TEST1
( C1 ) VALUES (
2
2);
1 row inserted
SQL> INSERT INTO TEST1
( C1 ) VALUES (
2
3);
1 row inserted
SQL> INSERT INTO TEST1
( C1 ) VALUES (
2
1);
1 row inserted
SQL> INSERT INTO TEST1
( C1 ) VALUES (
2
5);
1 row inserted
SQL> INSERT INTO TEST1
( C1 ) VALUES (
2
4);
1 row inserted
SQL> COMMIT;
Commit complete
SQL>
C1
2
3
1
5
4
select *
from test1
order by decode(
c1, (select min(c1) from
test1),
to_number(null), c1);
C1
2
3
4
5
1
|
****************************************************