Subqueries in Oracle
Subqueries are select statements which are part of main select statement.
Subqueries can be used in below clauses of a SELECT statement.
- WHERE
- HAVING
- FROM
- ORDER BY
Subqueries are of two types:
- Single row subqueries
- Multiple row subqueries
Usages of Subqueries:
Subqueries in WHERE clause:
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30; Using GROUP function in subqueries:
We want to view the list of employees of DEPARTMENT_ID 30 whose salary is greater than that of EMPLOYEE_ID 117 which is 2800.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY > (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117); We want to view the list of employees of DEPARTMENT_ID 30 whose salary is greater than the average salary of JOB_ID PU_CLERK.
SELECT ROUND(AVG(SALARY), 0) AVG_SALARY FROM EMP_SELECT WHERE DEPARTMENT_ID = 30 AND JOB_ID = 'PU_CLERK';
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY > (SELECT ROUND(AVG(SALARY), 0)
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND JOB_ID = 'PU_CLERK'); We can check that all the above employee's salary is greater than the average salary 2483 of JOB_ID PU_CLERK.
Subqueries in HAVING clause:
We want to view the JOB_ID wise average salary for DEPARTMENT_ID 50, where average salary is less than the departmental average salary.
JOB_ID wise average salary for DEPARTMENT_ID 50:
SELECT DEPARTMENT_ID, JOB_ID, ROUND(AVG(SALARY), 0) AVG_SALARY FROM EMP_SELECT WHERE DEPARTMENT_ID = 50 GROUP BY DEPARTMENT_ID, JOB_ID
Departmental average salary for DEPARTMENT_ID 50:
SELECT ROUND(AVG(SALARY), 0) DEPARTMENTAL_AVG_SALARY FROM EMP_SELECT WHERE DEPARTMENT_ID = 50;
JOB_ID wise average salary where average salary is less than the departmental average salary:
SELECT DEPARTMENT_ID, JOB_ID, ROUND(AVG(SALARY), 0) AVG_SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 50
GROUP BY DEPARTMENT_ID, JOB_ID
HAVING ROUND(AVG(SALARY), 0) < (SELECT ROUND(AVG(SALARY), 0)
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 50); In the above output both the average salaries are less than 3476.
We want to view the JOB_ID wise minimum salary for DEPARTMENT_ID 50, where minimum salary is less than the departmental average salary.
SELECT DEPARTMENT_ID, JOB_ID, MIN(SALARY) MIN_SALARY FROM EMP_SELECT WHERE DEPARTMENT_ID = 50 GROUP BY DEPARTMENT_ID, JOB_ID
Departmental average salary is 3476.
SELECT DEPARTMENT_ID, JOB_ID, MIN(SALARY) MIN_SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 50
GROUP BY DEPARTMENT_ID, JOB_ID
HAVING MIN(SALARY) < (SELECT ROUND(AVG(SALARY), 0)
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 50); In the above example both the minimum salaries are less than 3476.
Subqueries in FROM clause:
We want to view the DEPARTMENT_ID, JOB_ID wise minimum salary for DEPARMENT_ID 30 and 50.
SELECT DEPARTMENT_ID,
JOB_ID,
MIN_SALARY
FROM (SELECT DEPARTMENT_ID,
JOB_ID,
MIN(SALARY) MIN_SALARY
FROM EMP_SELECT
GROUP BY DEPARTMENT_ID, JOB_ID
)
WHERE DEPARTMENT_ID IN (30, 50)
ORDER BY DEPARTMENT_ID; We want to view the employee details and department details for DEPARTMENT_ID 30.
SELECT A.EMPLOYEE_ID,
A.FIRST_NAME,
A.LAST_NAME,
A.JOB_ID,
A.HIRE_DATE,
A.SALARY,
A.DEPARTMENT_ID,
B.DEPARTMENT_NAME,
B.LOCATION_ID
FROM EMP_SELECT A,
(SELECT DEPARTMENT_ID,
DEPARTMENT_NAME,
LOCATION_ID
FROM DEPARTMENTS
) B
WHERE A.DEPARTMENT_ID = 30
AND A.DEPARTMENT_ID = B.DEPARTMENT_ID
ORDER BY A.EMPLOYEE_ID; Subqueries in ORDER BY clause:
We want to view the employee details for DEPARTMENT_ID 30 and 50 order by DEPARTMENT_NAME.
SELECT DEPARTMENT_ID,
DEPARTMENT_NAME
FROM DEPARTMENTS
WHERE DEPARTMENT_ID IN (30, 90)
ORDER BY DEPARTMENT_NAME; We can check that while sorting the department data DEPARTMENT_NAME wise DEPARTMENT_ID 90 will come first.
SELECT A.EMPLOYEE_ID,
A.FIRST_NAME,
A.LAST_NAME,
A.JOB_ID,
A.HIRE_DATE,
A.SALARY,
A.DEPARTMENT_ID
FROM EMP_SELECT A
WHERE A.DEPARTMENT_ID IN (30, 90)
ORDER BY (SELECT DEPARTMENT_NAME
FROM DEPARTMENTS
WHERE DEPARTMENT_ID = A.DEPARTMENT_ID); Types of Subqueries:
Single row subqueries:
Single row subqueries return only one row from the inner select statement.
Single row operators are:
| Operators | Description |
|---|---|
| = | Equals To |
| > | Greater Than |
| >= | Greater Than or Equals To |
| < | Less Than |
| <= | Less Than or Equals To |
| <> | Not Equals To |
Equals To Operator (=):
We want to view the employee details where DEPARTMENT_ID is that of EMPLOYEE_ID 102.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 102; SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = (SELECT DEPARTMENT_ID
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 102); Greater Than (>):
We want to view the employee details of DEPARTMENT_ID 30 where salary is greater than that of EMPLOYEE_ID 117.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117; SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY > (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117); All the above employee's salary is grater than 2800.
Greater Than or Equals To (>=):
We want to view the employee details of DEPARTMENT_ID 30 where salary is greater than or quals to that of EMPLOYEE_ID 117.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY >= (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117); All the above employee's salary is grater than or equals to 2800.
Less Than (<):
We want to view the employee details of DEPARTMENT_ID 30 where salary is less than that of EMPLOYEE_ID 117.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY < (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117); All the above employee's salary is less than 2800.
Less Than or Equals To (<=):
We want to view the employee details of DEPARTMENT_ID 30 where salary is less than or quals to that of EMPLOYEE_ID 117.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY <= (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 117); All the above employee's salary is less than or equals to 2800.
Not Equals To (<>):
We want to view the employee details of DEPARTMENT_ID 60 where salary is not quals to 4800.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 60; SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 60;
AND SALARY <> (SELECT SALARY
FROM EMP_SELECT
WHERE EMPLOYEE_ID = 105); All the above employee's salary is not equals to 4800.
Multiple row subqueries:
Multiple row subqueries return more than one row from the inner select statement.
Multiple row operators are:
| Operators | Description |
|---|---|
| IN | Equals to any member in the subquery |
| ANY | It compares the value with each value returns by the subquery |
| ALL | It compares the value with maximum or minimum value returns by the subquery |
IN:
We want to view the employee details where DEPARTMENT_ID is that of EMPLOYEE_ID 102 and 117.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID
FROM EMP_SELECT
WHERE EMPLOYEE_ID IN (102, 117)); ANY:
Modified data of DEPARTMENT_ID 30.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
ORDER BY JOB_ID; We want to view the employee details of DEPARTMENT_ID 30 and JOB_ID PU_MAN whose salary is greater than any salary of JOB_ID PU_CLERK.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY > ANY(SELECT SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND JOB_ID = 'PU_CLERK')
AND JOB_ID <> 'PU_CLERK'; We want to view the employee details of DEPARTMENT_ID 30 and JOB_ID PU_MAN whose salary is less than any salary of JOB_ID PU_CLERK.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY < ANY(SELECT SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND JOB_ID = 'PU_CLERK')
AND JOB_ID <> 'PU_CLERK'; ALL:
We want to view the employee details of DEPARTMENT_ID 30 and JOB_ID PU_MAN whose salary is greater than the maximum salary of JOB_ID PU_CLERK.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY > ALL(SELECT SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND JOB_ID = 'PU_CLERK')
AND JOB_ID <> 'PU_CLERK'; The maximum salary of JOB_ID PU_CLERK is 3100. That's why above row is returned by the query.
We want to view the employee details of DEPARTMENT_ID 30 and JOB_ID PU_MAN whose salary is less than the minimum salary of JOB_ID PU_CLERK.
SELECT EMPLOYEE_ID,
FIRST_NAME,
LAST_NAME,
JOB_ID,
HIRE_DATE,
SALARY,
DEPARTMENT_ID
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND SALARY < ALL(SELECT SALARY
FROM EMP_SELECT
WHERE DEPARTMENT_ID = 30
AND JOB_ID = 'PU_CLERK')
AND JOB_ID <> 'PU_CLERK'; Based on DEPARTMENT_ID 30 data, the minimum salary of JOB_ID PU_MAN is 2300 which is greater than that of JOB_ID PU_CLERK 2000. That's why the above query does not return any row.
RELATED TOPICS: