SQL Queries Interview Questions - Oracle Part 1
SQL Queries Interview Questions - Oracle Part 1
SQL Queries Interview Questions - Oracle Part 1
As a database developer, writing SQL queries, PLSQL code is part of daily life. Having a good knowledge on
SQL is really important. Here i am posting some practical exampleson SQL queries.
To solve these interview questions on SQL queries you have to create the products, sales tables in your oracle
database. The "Create Table", "Insert" statements are provided below.
CREATE TABLE PRODUCTS
(
PRODUCT_ID
INTEGER,
PRODUCT_NAME VARCHAR2(30)
);
CREATE TABLE SALES
(
SALE_ID
INTEGER,
PRODUCT_ID
INTEGER,
YEAR
INTEGER,
Quantity
INTEGER,
PRICE
INTEGER
);
PRODUCT_ID PRODUCT_NAME
----------------------100
Nokia
200
IPhone
300
Samsung
-------------------------------------1
100
2010 25
5000
100
2011 16
5000
100
2012 8
5000
200
2010 10
9000
200
2011 15
9000
200
2012 20
9000
300
2010 20
7000
300
2011 18
7000
300
2012 20
7000
Here Quantity is the number of products sold in each year. Price is the sale price of each product.
I hope you have created the tables in your oracle database. Now try to solve the belowSQL queries.
1. Write a SQL query to find the products which have continuous increase in sales every year?
Solution:
Here Iphone is the only product whose sales are increasing every year.
STEP1: First we will get the previous year sales for each product. The SQL query to do this is
SELECT P.PRODUCT_NAME,
S.YEAR,
S.QUANTITY,
LEAD(S.QUANTITY,1,0) OVER (
PARTITION BY P.PRODUCT_ID
ORDER BY S.YEAR DESC
) QUAN_PREV_YEAR
FROM PRODUCTS P,
SALES S
WHERE P.PRODUCT_ID = S.PRODUCT_ID;
2012 8
16
Nokia
2011 16
25
Nokia
2010 25
IPhone
2012 20
15
IPhone
2011 15
10
IPhone
2010 10
Samsung
2012 20
18
Samsung
2011 18
20
Samsung
2010 20
Here the lead analytic function will get the quantity of a product in its previous year.
STEP2: We will find the difference between the quantities of a product with its previous years quantity. If this
difference is greater than or equal to zero for all the rows, then the product is a constantly increasing in sales. The
final query to get the required result is
SELECT PRODUCT_NAME
FROM
(
SELECT P.PRODUCT_NAME,
S.QUANTITY LEAD(S.QUANTITY,1,0) OVER (
PARTITION BY P.PRODUCT_ID
ORDER BY S.YEAR DESC
) QUAN_DIFF
FROM PRODUCTS P,
SALES S
WHERE P.PRODUCT_ID = S.PRODUCT_ID
)A
GROUP BY PRODUCT_NAME
HAVING MIN(QUAN_DIFF) >= 0;
PRODUCT_NAME
-----------IPhone
2. Write a SQL query to find the products which does not have sales at all?
Solution:
LG is the only product which does not have sales at all. This can be achieved in three ways.
Method1: Using left outer join.
SELECT P.PRODUCT_NAME
FROM PRODUCTS P
LEFT OUTER JOIN
SALES S
ON
(P.PRODUCT_ID = S.PRODUCT_ID);
PRODUCT_NAME
-----------LG
PRODUCT_NAME
-----------LG
PRODUCT_NAME
-----------LG
3. Write a SQL query to find the products whose sales decreased in 2012 compared to 2011?
Solution:
Here Nokia is the only product whose sales decreased in year 2012 when compared withthe sales in the year 2011.
The SQL query to get the required output is
SELECT P.PRODUCT_NAME
FROM PRODUCTS P,
SALES S_2012,
SALES S_2011
WHERE P.PRODUCT_ID = S_2012.PRODUCT_ID
AND S_2012.YEAR = 2012
AND S_2011.YEAR = 2011
AND S_2012.PRODUCT_ID = S_2011.PRODUCT_ID
AND S_2012.QUANTITY < S_2011.QUANTITY;
PRODUCT_NAME
-----------Nokia
PRODUCT_NAME YEAR
-------------------Nokia
2010
Samsung
IPhone
2011
2012
Samsung
2012
(P.PRODUCT_ID = S.PRODUCT_ID)
GROUP BY P.PRODUCT_NAME;
PRODUCT_NAME TOTAL_SALES
--------------------------LG
IPhone
Samsung
Nokia
0
405000
406000
245000
2010 25
IPhone
2012 20
Samsung
2012 20
Samsung
2010 20
2. Write a query to compare the products sales of "IPhone" and "Samsung" in each year? The output should look
like as
YEAR IPHONE_QUANT SAM_QUANT IPHONE_PRICE SAM_PRICE
--------------------------------------------------2010 10
20
9000
7000
2011 15
18
9000
7000
2012 20
20
9000
7000
Solution:
By using self-join SQL query we can get the required result. The required SQL query is
SELECT S_I.YEAR,
S_I.QUANTITY IPHONE_QUANT,
S_S.QUANTITY SAM_QUANT,
S_I.PRICE IPHONE_PRICE,
S_S.PRICE SAM_PRICE
FROM PRODUCTS P_I,
SALES S_I,
PRODUCTS P_S,
SALES S_S
WHERE P_I.PRODUCT_ID = S_I.PRODUCT_ID
AND P_S.PRODUCT_ID = S_S.PRODUCT_ID
AND P_I.PRODUCT_NAME = 'IPhone'
AND P_S.PRODUCT_NAME = 'Samsung'
AND S_I.YEAR = S_S.YEAR
PRODUCT_NAME YEAR
RATIO
----------------------------IPhone
2011 0.333333333
IPhone
2012 0.444444444
IPhone
2010 0.222222222
Nokia
2012 0.163265306
Nokia
2011 0.326530612
Nokia
2010 0.510204082
Samsung
2010 0.344827586
Samsung
2012 0.344827586
Samsung
2011 0.310344828
4. In the SALES table quantity of each product is stored in rows for every year. Now write a query to transpose
the quantity for each product and display it in columns? The output should look like as
PRODUCT_NAME QUAN_2010 QUAN_2011 QUAN_2012
-----------------------------------------IPhone
10
Samsung
Nokia
15
20
25
20
18
16
20
8
Solution:
Oracle 11g provides a pivot function to transpose the row data into column data. The SQL query for this is
SELECT * FROM
(
SELECT P.PRODUCT_NAME,
S.QUANTITY,
S.YEAR
FROM PRODUCTS P,
SALES S
WHERE (P.PRODUCT_ID = S.PRODUCT_ID)
)A
PIVOT ( MAX(QUANTITY) AS QUAN FOR (YEAR) IN (2010,2011,2012));
If you are not running oracle 11g database, then use the below query for transposing the row data into column
data.
SELECT P.PRODUCT_NAME,
YEAR NUM_PRODUCTS
-----------------2010
2011
2012
2. Write a query to display only friday dates from Jan, 2000 to till now?
Solution:
SELECT C_DATE,
TO_CHAR(C_DATE,'DY')
FROM
(
SELECT TO_DATE('01-JAN-2000','DD-MON-YYYY')+LEVEL-1 C_DATE
FROM DUAL
CONNECT BY LEVEL <=
(SYSDATE - TO_DATE('01-JAN-2000','DD-MON-YYYY')+1)
)
WHERE TO_CHAR(C_DATE,'DY') = 'FRI';
3. Write a query to duplicate each row based on the value in the repeat column? The input table data looks like as
below
Products, Repeat
---------------A,
B,
C,
Now in the output data, the product A should be repeated 3 times, B should be repeated 5 times and C should be
repeated 2 times. The output will look like as below
Products, Repeat
---------------A,
A,
A,
B,
B,
B,
B,
B,
C,
C,
Solution:
SELECT PRODUCTS,
REPEAT
FROM T,
( SELECT LEVEL L FROM DUAL
CONNECT BY LEVEL <= (SELECT MAX(REPEAT) FROM T)
)A
WHERE T.REPEAT >= A.L
ORDER BY T.PRODUCTS;
4. Write a query to display each letter of the word "SMILE" in a separate row?
S
M
I
L
E
Solution:
SELECT SUBSTR('SMILE',LEVEL,1) A
FROM DUAL
CONNECT BY LEVEL <=LENGTH('SMILE');
5. Convert the string "SMILE" to Ascii values? The output should look like as 83,77,73,76,69. Where 83 is the
ascii value of S and so on.
The ASCII function will give ascii value for only one character. If you pass a string to the ascii function, it will
give the ascii value of first letter in the string. Here i am providing two solutions to get the ascii values of string.
Solution1:
SELECT SUBSTR(DUMP('SMILE'),15)
FROM DUAL;
Solution2:
SELECT WM_CONCAT(A)
FROM
(
SELECT ASCII(SUBSTR('SMILE',LEVEL,1)) A
FROM DUAL
CONNECT BY LEVEL <=LENGTH('SMILE')
);
Here ram and vamsi are friends of sam; ram and jhon are friends of vamsi and so on. Now write a query to find
friends of friends of sam. For sam; ram,jhon,vijay and anand are friends of friends. The output should look as
Name, Friend_of_Firend
---------------------sam,
ram
sam,
jhon
sam,
vijay
sam,
anand
Solution:
SELECT f1.name,
f2.friend_name as friend_of_friend
FROM
friends f1,
friends f2
f1.friend_name = f2.name;
2. This is an extension to the problem 1. In the output, you can see ram is displayed as friends of friends. This is
because, ram is mutual friend of sam and vamsi. Now extend the above query to exclude mutual friends. The
outuput should look as
Name, Friend_of_Friend
---------------------sam,
jhon
sam,
vijay
sam,
anand
Solution:
SELECT f1.name,
f2.friend_name as friend_of_friend
FROM
friends f1,
friends f2
f1.friend_name = f2.name
AND
NOT EXISTS
(SELECT 1 FROM friends f3
WHERE f3.name = f1.name
AND f3.friend_name = f2.friend_name);
3. Write a query to get the top 5 products based on the quantity sold without using the row_number
analytical function? The source data looks as
200,
2009
B,
155,
2009
C,
455,
2009
D,
620,
2009
E,
135,
2009
F,
390,
2009
G,
999,
2010
H,
810,
2010
I,
910,
2010
J,
109,
2010
L,
260,
2010
M,
580,
2010
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
rownum r
from t
ORDER BY quantity_sold DESC
)A
WHERE r <= 5;
4. This is an extension to the problem 3. Write a query to produce the same output using row_number
analytical function?
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
row_number() OVER(
ORDER BY quantity_sold DESC) r
from t
)A
WHERE r <= 5;
5. This is an extension to the problem 3. write a query to get the top 5 products in eachyear based on the quantity
sold?
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
row_number() OVER(
PARTITION BY year
ORDER BY quantity_sold DESC) r
from t
)A
WHERE r <= 5;
INTEGER,
PRODUCT_NAME VARCHAR2(30)
);
PRODUCT_ID PRODUCT_NAME
----------------------100
Nokia
200
IPhone
300
Samsung
400
LG
500
BlackBerry
600
Motorola
Do not select the products which are already loaded in the target table with in the last 30 days.
Target table should always contain the products loaded in 30 days. It shouldnot contain the
(
PRODUCT_ID
INTEGER,
PRODUCT_NAME VARCHAR2(30),
INSERT_DATE DATE
);
The next step is to pick 5 products randomly and then load into target table. While selecting check whether the
products are there in the
INSERT INTO TGT_PRODUCTS
SELECT PRODUCT_ID,
PRODUCT_NAME,
SYSDATE INSERT_DATE
FROM
(
SELECT PRODUCT_ID,
PRODUCT_NAME
FROM PRODUCTS S
WHERE NOT EXISTS (
SELECT 1
FROM TGT_PRODUCTS T
WHERE T.PRODUCT_ID = S.PRODUCT_ID
)
ORDER BY DBMS_RANDOM.VALUE --Random number generator in oracle.
)A
The last step is to delete the products from the table which are loaded 30 days back.
DELETE FROM TGT_PRODUCTS
WHERE INSERT_DATE < SYSDATE - 30;
CONTENT_ID CONTENT_TYPE
----------------------1
MOVIE
MOVIE
AUDIO
AUDIO
MAGAZINE
MAGAZINE
Load only one content type at a time into the target table.
The target table should always contain only one contain type.
The loading of content types should follow round-robin style. First MOVIE, second AUDIO, Third
Solution:
First we will create a lookup table where we mention the priorities for the content types. The lookup table Create
Statement and data is shown below.
CREATE TABLE CONTENTS_LKP
(
CONTENT_TYPE VARCHAR2(30),
PRIORITY
INTEGER,
LOAD_FLAG INTEGER
);
AUDIO
MAGAZINE
Here if LOAD_FLAG is 1, then it indicates which content type needs to be loaded into the target table. Only one
content type will have LOAD_FLAG as 1. The other content types will have LOAD_FLAG as 0. The
target table structure is same as the source tablestructure.
The second step is to truncate the target table before loading the data
TRUNCATE TABLE TGT_CONTENTS;
The third step is to choose the appropriate content type from the lookup table to load the source data into the
target table.
INSERT INTO TGT_CONTENTS
SELECT CONTENT_ID,
CONTENT_TYPE
FROM CONTENTS
WHERE CONTENT_TYPE = (SELECT CONTENT_TYPE FROM CONTENTS_LKP WHERE
LOAD_FLAG=1);
UPDATE CONTENTS_LKP
SET LOAD_FLAG = 1
WHERE PRIORITY = (
SELECT DECODE( PRIORITY,(SELECT MAX(PRIORITY) FROM CONTENTS_LKP) ,1 , PRIORITY+1)
FROM CONTENTS_LKP
WHERE CONTENT_TYPE = (SELECT DISTINCT CONTENT_TYPE FROM TGT_CONTENTS)
);
This displays the last executed grep command and also prints the result set of the command on the terminal.
2. Search for a string in a file
This is the basic usage of grep command. It searches for the given string in the specified file.
grep "Error" logfile.txt
This searches for the string "Error" in the log file and prints all the lines that has the word "Error".
3. Searching for a string in multiple files.
grep "string" file1 file2
grep "string" file_pattern
This is also the basic usage of the grep command. You can manually specify the list of files you want to search or
you can specify a file pattern (use regular expressions) tosearch for.
4. Case insensitive search
The -i option enables to search for a string case insensitively in the give file. It matches the words like "UNIX",
"Unix", "unix".
grep -i "UNix" file.txt
Some times, if you are searching for an error in a log file; it is always good to know the lines around the
error lines to know the cause of the error.
grep -B 2 "Error" file.txt
This will prints the matched lines along with the two lines before the matched lines.
8. Displaying the lines after the match.
grep -A 3 "Error" file.txt
This will display the matched lines along with the three lines after the matched lines.
9. Displaying the lines around the match
grep -C 5 "Error" file.txt
This will display the matched lines and also five lines before and after the matched lines.
10. Searching for a sting in all files recursively
You can search for a string in all the files under the current directory and sub-directories with the help -r option.
grep -r "string" *
15. Display the file names that do not contain the pattern.
We can display the files which do not contain the matched string/pattern.
grep -l "string" file.txt
add.sh
logfile.txt
prime.pl
If you simply execute ls on the command prompt, then it will display the files and directories in the current
directory.
>ls /usr/local/bin
You can pass a directory as an argument to ls command. In this case, the ls command prints all the files and
directories in the specific directory you have passed.
2. Displaying the contents of a file.
The next thing is to display the contents of a file. The cat command is used to display thecontents in a file.
>cat file.txt
This is a sample unix file
Learning about unix server is awesome
8. Creating a directory.
Directories are a way of organizing your files. The mkdir command is used to create the specified directory.
>mkdir backup
To know about the unix command, it is always good to see the man pages. To see the man pages simply pass the
command as an argument to the man.
man ls
INTEGER,
PRODUCT_ID
INTEGER,
YEAR
INTEGER,
Quantity
INTEGER,
PRICE
INTEGER
);
100
2008 10
5000
100
2009 12
5000
100
2010 25
5000
100
2011 16
5000
100
2012 8
5000
200
2010 10
9000
200
2011 15
9000
200
2012 20
9000
200
2008 13
9000
10
200
2009 14
9000
11
300
2010 20
7000
12
300
2011 18
7000
13
300
2012 20
7000
14
300
2008 17
7000
15
300
2009 19
7000
YEAR CNT
--------2009 3
2010 3
2011 3
2008 3
2012 3
200
2008 13
9000 3
100
2008 10
5000 3
14
300
2008 17
7000 3
15
300
2009 19
7000 3
100
2009 12
5000 3
10
200
2009 14
9000 3
11
300
2010 20
7000 3
200
2010 10
9000 3
100
2010 25
5000 3
12
300
2011 18
7000 3
100
2011 16
5000 3
200
2011 15
9000 3
13
300
2012 20
7000 3
100
2012 8
5000 3
200
2012 20
9000 3
From the ouputs, you can observe that the aggregate functions return only one row per group whereas analytic
functions keeps all the rows in the gorup. Using the aggregate functions, the select clause contains only the
columns specified in group by clause and aggregate functions whereas in analytic functions you can specify all the
columns in thetable.
The PARTITION BY clause is similar to GROUP By clause, it specifies the window of rows that the analytic
funciton should operate on.
I hope you got some basic idea about aggregate and analytic functions. Now lets start with solving
the Interview Questions on Oracle Analytic Functions.
1. Write a SQL query using the analytic function to find the total sales(QUANTITY) of each product?
Solution:
SUM analytic function can be used to find the total sales. The SQL query is
SELECT PRODUCT_ID,
QUANTITY,
SUM(QUANTITY) OVER( PARTITION BY PRODUCT_ID ) TOT_SALES
FROM SALES;
12
71
100
10
71
100
25
71
100
16
71
100
71
200
15
72
200
10
72
200
20
72
200
14
72
200
13
72
300
20
94
300
18
94
300
17
94
300
20
94
300
19
94
2. Write a SQL query to find the cumulative sum of sales(QUANTITY) of each product? Here first sort the
QUANTITY in ascendaing order for each product and then accumulate the QUANTITY.
Cumulative sum of QUANTITY for a product = QUANTITY of current row + sum of QUANTITIES all previous
rows in that product.
Solution:
We have to use the option "ROWS UNBOUNDED PRECEDING" in the SUM analytic function to get the
cumulative sum. The SQL query to get the ouput is
SELECT PRODUCT_ID,
QUANTITY,
SUM(QUANTITY) OVER( PARTITION BY PRODUCT_ID
100
10
18
100
12
30
100
16
46
100
25
71
200
10
10
200
13
23
200
14
37
200
15
52
200
20
72
300
17
17
300
18
35
300
19
54
300
20
74
300
20
94
The ORDER BY clause is used to sort the data. Here the ROWS UNBOUNDED PRECEDING option specifies
that the SUM analytic function should operate on the current row and the pervious rows processed.
3. Write a SQL query to find the sum of sales of current row and previous 2 rows in a product group? Sort the data
on sales and then find the sum.
Solution:
The sql query for the required ouput is
SELECT PRODUCT_ID,
QUANTITY,
SUM(QUANTITY) OVER(
PARTITION BY PRODUCT_ID
ORDER BY QUANTITY DESC
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) CALC_SALES
FROM SALES;
25
25
100
16
41
100
12
53
100
10
38
100
30
200
20
20
200
15
35
200
14
49
200
13
42
200
10
37
300
20
20
300
20
40
300
19
59
300
18
57
300
17
54
The ROWS BETWEEN clause specifies the range of rows to consider for calculating the SUM.
4. Write a SQL query to find the Median of sales of a product?
Solution:
The SQL query for calculating the median is
SELECT PRODUCT_ID,
QUANTITY,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY QUANTITY ASC)
OVER (PARTITION BY PRODUCT_ID) MEDIAN
FROM SALES;
12
100
10
12
100
12
12
100
16
12
100
25
12
200
10
14
200
13
14
200
14
14
200
15
14
200
20
14
300
17
19
300
18
19
300
19
19
300
20
19
300
20
19
5. Write a SQL query to find the minimum sales of a product without using the group by clause.
Solution:
The SQL query is
SELECT PRODUCT_ID,
YEAR,
QUANTITY
FROM
(
SELECT PRODUCT_ID,
YEAR,
QUANTITY,
ROW_NUMBER() OVER(PARTITION BY PRODUCT_ID
ORDER BY QUANTITY ASC) MIN_SALE_RANK
FROM SALES
) WHERE MIN_SALE_RANK = 1;
2012
200
2010
10
300
2008
17
First Normal Form: Duplicate columns from the same table needs to be eliminated. We have to
create separate tables for each group of related data and identify each row with a unique column or set of columns
(Primary Key)
Second Normal Form: First it should meet the requirement of first normal form. Removes the subsets of
data that apply to multiple rows of a table and place them in separate tables. Relationships must be created
between the new tables and their predecessors through the use of foreign keys.
Third Normal Form: First it should meet the requirements of second normal form. Remove columns that
Atomic: Transactions must be atomic. Transactions must fail or succeed as a single unit.
Consistent: The database must always be in consistent state. There should not be any partial transactions
Isolation: The changes made by a user should be visible only to that user until the transaction is
committed.
MOLAP: The data is stored in multi-dimensional cube. The storage is not in the relational database, but in
proprietary formats.
ROLAP: ROLAP relies on manipulating the data stored in the RDBMS for slicing and dicing
functionality.
HOLAP: HOLAP combines the advantages of both MOLAP and ROLAP. For summary type information,
HOLAP leverages on cube technology for faster performance. For detail information, HOLAP can drill through
the cube.
example is the Employees and Departments table, where the row in the Departments table is referenced by one or
more rows in the Employees table.
9. Explain many-to-many relationship with an example?
Many-to-Many relationship is created between two tables by creating a junction table with the key from both the
tables forming the composite primary key of the junction table.
An example is Students, Subjects and Stud_Sub_junc tables. A student can opt for one or more subjects in a year.
Similarly a subject can be opted by one or more students. So a junction table is created to implement the many-tomany relationship.
10. Write down the general syntax of a select statement?
The basic syntax of a select statement is
SELECT Columns | *
FROM Table_Name
[WHERE Search_Condition]
[GROUP BY Group_By_Expression]
[HAVING Search_Condition]
[ORDER BY Order_By_Expression [ASC|DESC]]
2011 X
2011 Y
2011 Z
Here, in the output we will concatenate the products in each year by a comma separator. The desired output is:
year product_list
-----------------2010 A,B,C,D
2011 X,Y,Z
products
GROUP BY year;
WM_CONCAT function:
You cannot pass an explicit delimiter to the WM_CONCAT function. It uses comma as the string separator.
SELECT year,
wm_concat(product) AS product_list
FROM
products
GROUP BY year;
product
price
-------------------------------------1
10
20
30
40
50
60
70
80
The rows of the "sales" table needs to be converted into columns as shown below
Table Name: sales_rev
cutomer_id a_product b_product c_product
----------------------------------------1
10
20
30
40
50
60
70
80
If you are not using oracle 11g database, then you can implement the unpivot feature asconverting rows to
columns
Unpivot:
Unpivot operator converts the columns into rows.
Table Name: sales_rev
cutomer_id a_product b_product c_product
----------------------------------------1
10
20
30
40
50
60
70
80
10
20
30
40
50
60
70
80
The columns price and product in the unpivot clause are required and these names need not to be present
in the table.
10
10
10
10
10
10
10
11
20
20
I want to find the minimum and maximum values of continuous Emp_Seq numbers. The output should look as.
Dept_Id Min_Seq Max_Seq
----------------------10
10
10
10
11
11
20
Write an SQL query in oracle to find the minimum and maximum values of continuous Emp_Seq in each
department?
STEP1: First we will generate unique sequence numbers in each department using the Row_Number analytic
function in the Oracle. The SQL query is.
SELECT Dept_Id,
Emp_Seq,
ROW_NUMBER() OVER (PARTITION BY Dept_Id ORDER BY Emp_Seq) rn
FROM
employees;
Dept_Id Emp_Seq rn
-------------------10
10
10
10
10
10
10
10
11
20
20
STEP2: Subtract the value of rn from emp_seq to identify the continuous sequences as a group. The SQL query is
SELECT Dept_Id,
Emp_Seq,
Emp_Seq-ROW_NUMBER() OVER (PARTITION BY Dept_Id ORDER BY Emp_Seq) Dept_Split
FROM
employees;
10
10
10
10
10
10
10
11
20
20
STEP3: The combination of the Dept_Id and Dept_Split fields will become the group for continuous rows. Now
use group by on these fields and find the min and max values. The final SQL query is
SELECT Dept_Id,
MIN(Emp_Seq) Min_Seq,
MAX(Emp_Seq) Max_Seq
FROM
(
SELECT Dept_Id,
Emp_Seq,
Emp_Seq-ROW_NUMBER() OVER (PARTITION BY Dept_Id ORDER BY Emp_Seq) Dept_Split
FROM
employees;
)A
Group BY Dept_Id, Dept_Split
Tuning an SQL query for performance is a big topic. Here I will just cover how to re-write a query and thereby
improve the performance. Rewriting an SQL query is one of the ways you can improve performance. You can
rewrite a query in many different ways.
To explain this, i have used the sales and products table.
SALES(SALE_ID, YEAR, PRODUCT_ID, PRICE);
PRODUCTS(PRODUCT_ID, PRODUCT_NAME);
Follow the below steps in re writing a query for optimization.
1. Avoid Redundant Logic
I have seen people writing redundant sub-queries and worrying about their query performance. As an example,
find the total sales in each year and also the sales of product with id 10 in each year.
SELECT T.YEAR,
T.TOT_SAL,
P.PROD_10_SAL
(
SELECT YEAR,
SUM(PRICE) TOT_SAL
FROM SALES
GROUP BY YEAR
)T
LEFT OUTER JOIN
(
SELECT YEAR,
SUM(PRICE) PROD_10_SAL
FROM SALES
WHERE PRODUCT_ID = 10
)P
ON (T.YEAR = P.YEAR);
Most SQL developers write the above Sql query without even thinking that it can be solved in a single query. The
above query is rewritten as
SELECT YEAR,
SUM(CASE WHEN PRODUCT_ID = 10
THEN PRICE
ELSE NULL
END ) PROD_10_SAL,
SUM(SALES) TOT_SAL
FROM SALES
GROUP BY YEAR;
Now you can see the difference, just by reading the sales table one time we will able to solve the problem.
First take a look at of your query, identify the redundant logic and then tune it.
2. LEFT OUTER JOIN, NOT EXISTS, NOT IN
Some times you can rewrite a LEFT OUTER JOIN by using NOT EXISTS or NOT IN and vice versa. As an
example, I want to find the products which do not sold in the year 2011.
SELECT P.PRODUCT_ID,
P.PRODUCT_NAME
FROM PRODUCTS P
LEFT OUTER JOIN
SALES S
ON (P.PRODUCT_ID = S.PRODUCT_ID)
The same query can be rewritten using NOT EXISTS and NOT IN as
SELECT P.PRODUCT_ID,
P.PRODUCT_NAME
FROM PRODUCTS P
WHERE NOT EXISTS
(
SELECT 1
FROM SALES S
WHERE S.PRODUCT_ID = P.PRODUCT_ID);
SELECT P.PRODUCT_ID,
P.PRODUCT_NAME
FROM PRODUCTS P
WHERE PRODUCT_ID NOT IN
(
SELECT PRODUCT_ID
FROM SALES
);
Analyze the performance of these three queries and use the appropriate one.
Note: Be careful while using the NOT IN. If the sub query returns at lease row with NULL data, then the main
As we are not selecting any columns from the products table, we can rewrite the same query with the help of
EXISTS or IN operator.
SELECT S.PRODUCT_ID,
SUM(PRICE)
FROM SALES S
WHERE EXISTS
(
SELECT 1
FROM PRODUCTS P
WHERE P.PRODUCT_ID = S.PRODUCT_ID);
GROUP BY S.PRODUCT_ID;
SELECT S.PRODUCT_ID,
SUM(PRICE)
FROM SALES S
WHERE PRODUCT_ID IN
(
SELECT PRODUCT_ID
FROM PRODUCTS P
);
GROUP BY S.PRODUCT_ID;
FROM PRODUCTS P
WHERE P.PRODUCT_ID = S.PRODUCT_ID)
FROM SALES S
Analyze these two queries with the explain plan and check which one gives better performance.
5. Using With Clause or Temporary Tables.
Try to avoid writing complex Sql queries. Split the queries and store the data in temporary tables or use the Oracle
With Clause for temporary storage. This will improve the performance. You can also use the temporary tables or
with clause when you want to reuse the same query more than once. This saves the time and increases the
performance.
Tips for increasing the query performance:
Create the required indexes. In the mean time avoid creating too many indexes on a table.
Use the explain plan, auto trace to know about the query execution.
Ask the DBA to watch the query and gather stats like CPU usage, number of row read etc.
2. Write a command to search for the file 'map' in the current directory?
find -name map -type f
3. How to display the first 10 characters from each line of a file?
cut -c -10 filename
4. Write a command to remove the first number on all lines that start with "@"?
sed '\,^@, s/[0-9][0-9]*//' < filename
5. How to print the file names in a directory that has the word "term"?
grep -l term *
The '-l' option make the grep command to print only the filename without printing the content of the file. As soon
as the grep command finds the pattern in a file, it prints the pattern and stops searching other lines in the file.
6. How to run awk command specified in a file?
awk -f filename
7. How do you display the calendar for the month march in the year 1985?
The cal command can be used to display the current month calendar. You can pass the month and year
as arguments to display the required year, month combination calendar.
cal 03 1985
This will display the calendar for the March month and year 1985.
8. Write a command to find the total number of lines in a file?
wc -l filename
Other ways to pring the total number of lines are
awk 'BEGIN {sum=0} {sum=sum+1} END {print sum}' filename
awk 'END{print NR}' filename
9. How to duplicate empty lines in a file?
sed '/^$/ p' < filename
10. Explain iostat, vmstat and netstat?
Vmstat: reports on virtual memory statistics for processes, disk, tape and CPU activity.
4. Write a command to print the lines which end with the word "end"?
grep 'end$' filename
The '$' symbol specifies the grep command to search for the pattern at the end of the line.
5. Write a command to select only those lines containing "july" as a whole word?
grep -w july filename
The '-w' option makes the grep command to search for exact whole words. If the specified pattern is found in a
string, then it is not considered as a whole word. For example: In the string "mikejulymak", the pattern "july" is
found. However "july" is not a whole word in that string.
6. How to remove the first 10 lines from a file?
sed '1,10 d' < filename
7. Write a command to duplicate each line in a file?
sed 'p' < filename
8. How to extract the username from 'who am i' comamnd?
who am i | cut -f1 -d' '
9. Write a command to list the files in '/usr' directory that start with 'ch' and then display the number of lines in
each file?
wc -l /usr/ch*
Another way is
find /usr -name 'ch*' -type f -exec wc -l {} \;
10. How to remove blank lines in a file ?
grep -v ^$ filename > new_filename
6. How to replace the word "Gun" with "Pen" in the first 100 lines of a file?
sed '1,00 s/Gun/Pen/' < filename
7. Write a Unix command to display the lines in a file that do not contain the word "RAM"?
grep -v RAM filename
The '-v' option tells the grep to print the lines that do not contain the specified pattern.
8. How to print the squares of numbers from 1 to 10 using awk command
awk 'BEGIN { for(i=1;i<=10;i++) {print "square of",i,"is",i*i;}}'
9. Write a command to display the files in the directory by file size?
ls -l | grep '^-' |sort -nr -k 5
10. How to find out the usage of the CPU by the processes?
The top utility can be used to display the CPU usage by the processes.
1. Write a command to print the lines that has the the pattern "july" in all the files in a particular directory?
grep july *
This will print all the lines in all files that contain the word july along with the file name. If any of the files
contain words like "JULY" or "July", the above command would not print those lines.
2. Write a command to print the lines that has the word "july" in all the files in a directory and also suppress the
filename in the output.
grep -h july *
3. Write a command to print the lines that has the word "july" while ignoring the case.
grep -i july *
The option i make the grep command to treat the pattern as case insensitive.
4. When you use a single file as input to the grep command to search for a pattern, it won't print the filename in
the output. Now write a grep command to print the filename in the output without using the '-H' option.
grep pattern filename /dev/null
The /dev/null or null device is special file that discards the data written to it. So, the /dev/null is always an empty
file.
Another way to print the filename is using the '-H' option. The grep command for this is
grep -H pattern filename
5. Write a command to print the file names in a directory that does not contain the word "july"?
grep -L july *
The '-L' option makes the grep command to print the filenames that do not contain the specified pattern.
6. Write a command to print the line numbers along with the line that has the word "july"?
grep -n july filename
The '-n' option is used to print the line numbers in a file. The line numbers start from 1
7. Write a command to print the lines that starts with the word "start"?
grep '^start' filename
The '^' symbol specifies the grep command to search for the pattern at the start of the line.
8. In the text file, some lines are delimited by colon and some are delimited by space. Write a command to print
the third field of each line.
awk '{ if( $0 ~ /:/ ) { FS=":"; } else { FS =" "; } print $3 }' filename
9. Write a command to print the line number before each line?
awk '{print NR, $0}' filename
10. Write a command to print the second and third line of a file without using NR.
awk 'BEGIN {RS="";FS="\n"} {print $2,$3}' filename
11. How to create an alias for the complex command and remove the alias?
The alias utility is used to create the alias for a command. The below command createsalias for ps -aef command.
alias pg='ps -aef'
If you use pg, it will work the same way as ps -aef.
To remove the alias simply use the unalias command as
unalias pg
12. Write a command to display todays date in the format of 'yyyy-mm-dd'?
The date command can be used to display todays date with time
date '+%Y-%m-%d'