Tricky SQL Queries For Interview
Tricky SQL Queries For Interview
other websites and the original links have been provided. The sole purpose is to provide a collection of queries in one
place.
The solutions will work in ORACLE database. It may or may not work in other databases(depending on the portability
of the SQL queries). In cases where the solutions are not working, the question or the logic may be taken and an
The solutions provided in no case may be optimal. Better(efficient/alternate) solutions can be shared as we are all
Any error that may have crept in inadvertently may be pointed out.
and http://oddabout.com/?page_id=2210
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 create table neg_pos(num number);
insert into neg_pos values(-1);
3 insert into neg_pos values(-2);
4 insert into neg_pos values(-3);
5 insert into neg_pos values(-4);
6 insert into neg_pos values(1);
insert into neg_pos values(2);
7
insert into neg_pos values(3);
8 insert into neg_pos values(4);
9 commit;
10
1
2 select * from neg_pos ;
num
3 -1
4 -2
5 -3
6 -4
1
7
2
8 3
9 4
10
Answer :
1 SELECT
2 SUM(CASE WHEN num < 0 THEN num ELSE 0 END) neg,
3 SUM(CASE WHEN num > 0 THEN num ELSE 0 END)pos
FROM neg_pos;
4
gives
————-
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
Using the escape character ( to search for strings containing like ‘ABC %%TRF’, ‘TR%FF’ or ‘%GH’)
Answer :
1 SELECT col_name FROM tbl_name
2 WHERE col_name LIKE '%?%%' ESCAPE '?';
Another solution:
1 SELECT col_name FROM tbl_name
2 WHERE instr(col_name,'%') > 0
****************************************************
translate(‘string’,'to_replace’,'replace_with’)
for eg:
1 SELECT translate
2 ('asdfsd@#@$#$%$sdfg&;','!@#$%^&;*()_+=-`~?><:/.,',' ') FROM dual;
will return—asdfsdsdfg
To remove quotes, use two quotes for every single quote as shown below:
1 CREATE TABLE test_quote(quote VARCHAR2(5));
2 INSERT INTO test_quote VALUES ('L''uck');
3 SELECT * FROM test_quote;
SELECT REPLACE(quote,'''','') from test_quote;
4
A table has columns with numbers and numbers with alphabets. Write a query to select only those rows
col1
——
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
Answer:
1 SELECT CASE WHEN ascii(substr('99/98',1,1)) BETWEEN 48 AND 57
2 AND ascii(substr('99/98',2,1)) BETWEEN 48 AND 57
3 AND substr('99/98',3,1) ='/'
4 AND ascii(substr('99/98',4,1)) BETWEEN 48 AND 57
AND ascii(substr('99/98',5,1)) BETWEEN 48 AND 57
5
THEN 'number' ELSE 'not num' END FROM dual;
6
****************************************************
5. From the given table, find those employees who are more than 21 years of age.
1
2 CREATE TABLE find_age(NAME Varchar2(10), dob DATE);
INSERT INTO find_age VALUES('AAA',to_date('06/02/1983','DD/MM/YYYY'));
3 INSERT INTO find_age VALUES('BBB',to_date('06/02/1967','DD/MM/YYYY'));
4 INSERT INTO find_age VALUES('CCC',to_date('02/06/1983','DD/MM/YYYY'));
5 INSERT INTO find_age VALUES('DDD',to_date('03/06/1983','DD/MM/YYYY'));
6 INSERT INTO find_age VALUES('EEE',to_date('04/06/1999','DD/MM/YYYY'));
7 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'));
8 INSERT INTO find_age VALUES('HHH',to_date('02/06/1990','DD/MM/YYYY'));
9 INSERT INTO find_age VALUES('III',to_date('03/06/1990','DD/MM/YYYY'));
10 COMMIT;
11
Answer:
1 SELECT NAME FROM find_age
2 WHERE dob < (SELECT add_months(SYSDATE,-(12*21)) FROM dual);
*corrected after the comment.
****************************************************
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 CREATE TABLE stu_dept(stu_name VARCHAR2(30), dept VARCHAR2(30));
3 INSERT INTO stu_dept VALUES('AAA','D1');
4 INSERT INTO stu_dept VALUES('BBB','D1');
5 INSERT INTO stu_dept VALUES('CCC','D1');
INSERT INTO stu_dept VALUES('DDD','D1');
6 INSERT INTO stu_dept VALUES('EEE','D2');
7 INSERT INTO stu_dept VALUES('FFF','D2');
8 INSERT INTO stu_dept VALUES('GGG','D2');
9 INSERT INTO stu_dept VALUES('HHH','D3');
10 INSERT INTO stu_dept VALUES('III','D3');
INSERT INTO stu_dept VALUES('JJJ','D3');
11 INSERT INTO stu_dept VALUES('KKK','D3');
12 INSERT INTO stu_dept VALUES('LLL','D3');
13
14 CREATE TABLE dept_cap(dept VARCHAR2(5),capacity NUMBER);
15 INSERT INTO dept_cap VALUES('D1',5);
INSERT INTO dept_cap VALUES('D2',5);
16
INSERT INTO dept_cap VALUES('D3',5);
17
18
Answer:
1 SELECT a.dept,a.capacity-t.cap remaining_seats
2 FROM dept_cap a,
3 (SELECT dept,COUNT(dept)cap FROM stu_dept
4 GROUP BY dept)t
5 WHERE a.dept=t.dept
AND t.cap<a.capacity;
6
****************************************************
or
1 SELECT ROWNUM FROM dual
2 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
****************************************************
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 CREATE TABLE test_number(id NUMBER,SEQ NUMBER,text VARCHAR2(5)) ;
INSERT INTO test_number VALUES(1,1,'AA');
4 INSERT INTO test_number VALUES(1,3,'CC');
5 INSERT INTO test_number VALUES(1,4,'DD');
6 INSERT INTO test_number VALUES(1,5,'EE');
7 INSERT INTO test_number VALUES(1,6,'FF');
8 INSERT INTO test_number VALUES(1,7,'GG');
INSERT INTO test_number VALUES(1,8,'HH');
9 INSERT INTO test_number VALUES(1,10,'JJ');
10 INSERT INTO test_number VALUES(2,1,'KK');
11 INSERT INTO test_number VALUES(2,2,'LL');
12 INSERT INTO test_number VALUES(2,3,'MM');
INSERT INTO test_number VALUES(2,4,'NN');
13
INSERT INTO test_number VALUES(2,6,'PP');
14 INSERT INTO test_number VALUES(2,7,'QQ');
15 INSERT INTO test_number VALUES(3,1,'TT');
16 INSERT INTO test_number VALUES(3,4,'ZZ');
17 INSERT INTO test_number VALUES(3,5,'XX');
18
create tabel test_number_min_max(id number,mn number,mx number);
19 INSERT INTO test_number_min_max VALUES(1,1,12);
20 INSERT INTO test_number_min_max VALUES(2,1,9);
21 INSERT INTO test_number_min_max VALUES(3,1,5);
22
23
Answer:
1 SELECT r id,rn seq FROM (SELECT ROWNUM rn FROM all_objects WHERE ROWNUM
2 <13),
3 (SELECT ROWNUM r FROM all_objects
WHERE ROWNUM <4),test_number_min_max m
4 WHERE r=id
5 AND rn >= mn
6 AND rn <= mx
7 AND (r,rn) NOT IN
8 (SELECT id,seq FROM test_number)
OR
1 SELECT r id ,l seq FROM
(SELECT LEVEL l FROM dual
2
CONNECT BY LEVEL <13),
3
4 (SELECT LEVEL r FROM dual CONNECT BY LEVEL <4),
5 test_number_min_max
6 WHERE r=id
7 AND l>=mn
8 AND l<=mx
AND (r,l) NOT IN (SELECT id,seq FROM test_number)
9
OUTPUT :
ID SEQ
12
19
1 11
1 12
25
28
29
32
33
****************************************************
1LR
—————
111
112
113
121
122
123
131
132
133
Answer:
1 SELECT * FROM
2 (SELECT 1 FROM dual),
3 (SELECT LEVEL l FROM dual CONNECT BY LEVEL <4),
(SELECT LEVEL r FROM dual CONNECT BY LEVEL <4);
4
****************************************************
10. Check the Input and Output and try to figure out the question.
1 CREATE TABLE test_output(NAME VARCHAR2(5), city VARCHAR2(6), num NUMBER);
INSERT INTO test_output VALUES ('AN','TTT',5);
2
3 INSERT INTO test_output VALUES ('AN','TTT',6);
INSERT INTO test_output VALUES ('AN','TTT',7);
4 INSERT INTO test_output VALUES ('BB','RRR',8);
5 INSERT INTO test_output VALUES ('BB','RRR',9);
6 INSERT INTO test_output VALUES ('BB','RRR',10);
7
Input :
NAME CITY NUM
AN TTT 5
AN TTT 6
AN TTT 7
BB RRR 8
BB RRR 9
BB RRR 10
Answer :
1 SELECT (CASE WHEN rn=1 THEN NAME ELSE NULL END) NAME,
2 (CASE WHEN rn=1 THEN CITY ELSE NULL END ) CITY,
3 num
4 FROM
5 (SELECT NAME,city,num,
row_number() over(PARTITION BY NAME,city ORDER BY NAME) rn
6 FROM test_output);
7
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
ALPA RANK
———-
a1
b2
c4
x5
y6
z8
9g
0f
7e
3d
OUTPUT:
AB
——–
0f
1a
2b
3d
4c
5x
6y
7e
8z
9g
Answer:
1 SELECT least(alpa,rank) a,greatest(alpa,rank) b FROM test_b
2 ORDER BY 1
****************************************************
13. One of the most common question asked in interviews. To find the second (or third or fourth…) nth
GROUP_ID VAL RN
———————-
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
SELECT DISTINCT f.group_id,
2 CASE WHEN o.val > 0 THEN to_char(o.val) ELSE 'N/A' END val
3 FROM find_rank f
4 LEFT OUTER JOIN
5 (SELECT DISTINCT group_id,val FROM
6 (SELECT group_id,val,
7 dense_rank() over (PARTITION BY group_id ORDER BY val DESC) rn
FROM find_rank) t
8 WHERE t.rn=&rank)o
9 ON f.group_id=o.group_id
10
with &rank =3
GROUP_ID VAL
——————-
G1 12
G2 10
G3 1
G4 N/A
G5 -3
****************************************************
14. Another common interview question. To transform column into rows.
1
2 CREATE TABLE col_to_rows(stu_name VARCHAR2(30),
3 subject VARCHAR2(10),marks NUMBER);
4 INSERT INTO col_to_rows VALUES('GEORGE','ECO',77);
5 INSERT INTO col_to_rows VALUES('GEORGE','HIS',99);
6 INSERT INTO col_to_rows VALUES('GEORGE','MAT',64);
INSERT INTO col_to_rows VALUES('GEORGE','GEO',85);
7 INSERT INTO col_to_rows VALUES('GEORGE','SCI',98);
8 INSERT INTO col_to_rows VALUES('ROBERT','ECO',71);
9 INSERT INTO col_to_rows VALUES('ROBERT','HIS',90);
10 INSERT INTO col_to_rows VALUES('ROBERT','MAT',84);
INSERT INTO col_to_rows VALUES('ROBERT','GEO',95);
11
INSERT INTO col_to_rows VALUES('ROBERT','SCI',58);
12 INSERT INTO col_to_rows VALUES('TIMOTHY','ECO',56);
13 INSERT INTO col_to_rows VALUES('TIMOTHY','HIS',55);
14 INSERT INTO col_to_rows VALUES('TIMOTHY','MAT',67);
15 INSERT INTO col_to_rows VALUES('TIMOTHY','GEO',54);
INSERT INTO col_to_rows VALUES('TIMOTHY','SCI',45);
16 COMMIT;
17
18
Answer :
1
SELECT stu_name,
2 max(CASE WHEN subject='ECO' THEN marks ELSE 0 END) ECO,
3 max(CASE WHEN subject='HIS' THEN marks ELSE 0 END) HIS,
4 max(CASE WHEN subject='MAT' THEN marks ELSE 0 END) MAT,
5 max(CASE WHEN subject='GEO' THEN marks ELSE 0 END) GEO,
max(CASE WHEN subject='SCI' THEN marks ELSE 0 END) SCI
6
FROM col_to_rows
7 GROUP BY stu_name
8
OR
1 SELECT stu_name,
2 MAX(decode(subject,'ECO',marks,0)) ECO,
3 MAX(decode(subject,'HIS',marks,0)) HIS,
4 MAX(decode(subject,'MAT',marks,0)) MAT,
5 MAX(decode(subject,'GEO',marks,0)) GEO,
MAX(decode(subject,'SCI',marks,0)) SCI
6 FROM col_to_rows GROUP BY stu_name
7
OR
1 SELECT stu_name,
2 max(CASE WHEN rn=1 THEN marks ELSE 0 END) ECO,
3 max(CASE WHEN rn=2 THEN marks ELSE 0 END) GEO,
max(CASE WHEN rn=3 THEN marks ELSE 0 END) HIS,
4 max(CASE WHEN rn=4 THEN marks ELSE 0 END) MAT,
5 max(CASE WHEN rn=5 THEN marks ELSE 0 END) SCI FROM
6 (SELECT stu_name,subject,marks, rank() over (PARTITION BY stu_name ORDER BY subject )rn
7 FROM col_to_rows)
8 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
****************************************************
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 SQL> CREATE TABLE TEST1 (c1 NUMBER(2));
2
Table created
3
4
SQL> INSERT INTO TEST1 ( C1 ) VALUES (
5 2 2);
6
7 1 row inserted
8
9 SQL> INSERT INTO TEST1 ( C1 ) VALUES (
10 2 3);
11
1 row inserted
12
13 SQL> INSERT INTO TEST1 ( C1 ) VALUES (
14 2 1);
15
16 1 row inserted
17
18 SQL> INSERT INTO TEST1 ( C1 ) VALUES (
19 2 5);
20
1 row inserted
21
22 SQL> INSERT INTO TEST1 ( C1 ) VALUES (
23 2 4);
24
25 1 row inserted
26
27 SQL> COMMIT;
28
Commit complete
29
30 SQL>
31
32 C1
33 2
34
35
36
37 3
38 1
5
39 4
40
41 select * from test1
42 order by decode( c1, (select min(c1) from test1), to_number(null), c1);
43
44 C1
2
45
3
46 4
47 5
48 1
49
50
51
****************************************************
Post to Blogger
Post to Delicious
Post to Digg
Post to Facebook
5
5
Post to StumbleUpon
Post to Twitter
1.
admin says:
July 1, 2011 at 10:02 pm
for more queries visit
http://oddabout.com/?page_id=1907
reply
2.
unknown says:
September 4, 2012 at 10:44 am
very nice collection of queries….helped me alot…thanks
reply
3.
jatin says:
October 16, 2012 at 1:58 pm
very tricky, took time to understand them and very soon use them, quite helpful too
reply
4.
Ram says:
December 5, 2012 at 11:25 pm
Very Useful…….Appreciate efforts for putting very useful info.
reply
5.
Vimal says:
March 4, 2013 at 8:01 pm
Hello,
6.
Nishu says:
April 7, 2013 at 6:25 pm
Buddy nice collection of queries helpde me a lot..keep finding more things like this..Thanks!!!
reply
7.
Sankar says:
May 16, 2013 at 10:33 pm
Thanks a lot for your effort.It helped me a lot.
reply
8.
dipu says:
May 17, 2013 at 8:42 pm
10. How to solve it
=============================
=============================
AN TTT 5
—————————–
6
—————————–
SSS 7
—————————–
BB SSS 8
—————————–
GGG 9
—————————–
10
=============================
reply
dipu says:
May 17, 2013 at 8:49 pm
Output :
NAMECITYNUM
ANTTT5
SSS7
BBSSS8
GGG9
10
reply
pradeep says:
May 20, 2013 at 1:07 pm
SELECT (CASE WHEN rn=1 and num=5 or num=8 THEN NAME ELSE ” END) NAME,
(CASE WHEN rn=1 or city=’sss’ and name=’bb’ THEN CITY ELSE ” END ) CITY,
num
FROM
(SELECT NAME,city,num,
pradeep says:
May 20, 2013 at 1:12 pm
SELECT (CASE WHEN rn=1 and num=5 or num=8 THEN NAME ELSE ” END) NAME,
(CASE WHEN rn=1 or city=’sss’ and name=’bb’ THEN CITY ELSE ” END ) CITY,
num
FROM
(SELECT NAME,city,num,
Garuda says:
January 29, 2014 at 6:25 pm
Thanks a lot for your effort.
Tanvi Garg says:
March 26, 2014 at 2:40 pm
a more generic approach, without the hard coded city name could be as follows:-
select case when rn_name = 1 then name else ‘ ‘ end as name, case when rn_city = 1 then city else ‘ ‘ end as
city,num from
(select name, CITY,num,row_number() over ( partition by name order by city desc) rn_name,
row_number() over ( partition by name,city order by city desc) rn_city from test_output) a;
SIva says:
February 18, 2015 at 2:47 pm
Another generalised approach: hope it might help
from(select row_number() over (partitioned by name,city) as rn_1, row_number() over (partitioned by name) as rn_2
,name,city,num) select (case when rn_1 =1 and rn_2 =1 then Name when rn_1 = 1 and rn_2!=1 then city else num
end) as name,
(case when rn_1=1 and rn_2 = 1 then city when rn_1=1 and rn_2 !=1 then num else null end) as city,
(case when rn_1=1 and rn_2 =1 then num else null end) as num;
Anudeep Jaiswal says:
March 16, 2015 at 11:44 am
WITH CTE
AS (SELECT Name,
City,
NUM,
Row_number()
OVER(
FROM test_output)
SELECT Ltrim(Rtrim(CASE WHEN ID = 1 THEN Name ELSE ” END + ‘ ‘ + CASE WHEN ID = 1 THEN City ELSE ”
FROM CTE