Joins & Sub-queries

Oracle recognizes that you may want data that resides in multiple tables drawn together in some meaningful way. One of the most important features of the SQL is that it allows establishing relationship among multiple tables and helps to retrieve information from multiple tables. With joins, the information from any number of tables can be related. Rows in one table can be joined to rows in another table according to common values existing in corresponding columns, that is, usually primary and foreign key columns.

A primary key is used in a table to identify the uniqueness of each row in a table. The table in which the column appears as a primary key is referred to as the parent table, while the column that references the other table in the relationship is often called the child table. The column in the child table relates to the parent table is called a foreign key. A "Join" can be recognized in a SQL SELECT statement if it has more than one table after the FROM keyword.

For example: SELECT "list-of-columns" FROM table1, table2 [WHERE "search-condition(s)"]  When writing the SELECT statement that joins tables, precede the column name with the table name for clarity and to enhance the database access. If the same column appears in more than one table, the column name must be prefixed with the table name. To join n tables, we require a minimum of n-1 join conditions. Therefore to join three tables a minimum of two joins are required, This rule does not apply if your table has a concatenated primary key, in which case more than one column is required to uniquely identify each row. In a join, the table names are listed in FROM clause, separated by comma.

Joins can be explained easier by demonstrating what would happen if you worked with one table only, and didn't have the ability to use "joins". This single table database is also sometimes referred to as a "flat table". Let's say you have a one-table database that is used to keep track of all your employees and departments:   EMPNO ENAME JOB SAL COMM DEPTNO DNAME LOC  Every time a new row is inserted into the table, all columns will be updated, thus resulting in unnecessary "redundant data".

Types of Join There are four types of Joins. These are: • • • • Equi Join Cartesian Join Outer Join Self Join

Equi Join or Inner Join The Inner Join or Equi Join returns all rows from both tables where there is a match. Or in other words, if the query is relating two tables using an equality operator (=), it is an equality join, also known as an inner join or an Equi Join. Syntax: SELECT field1, field2, field3FROM first_table ,second_table WHERE first_table.keyfield = second_table.foreign_keyfield; Example:

List the employee name with their department names.

SQL>SELECT ename, dname FROM Emp,dept where emp.deptno=dept.deptno ;  The Output is:   ENAME DNAME

We have seen that we have to type the names of the table before the common columns between the tables. Just as a column alias gives a column another name, a table alias gives table another name. Table aliases help to keep SQL code smaller, therefore it uses less memory. We can use table aliases in the FROM clause. These aliases are valid only for the current SELECT statement. Table aliases can also be used in the SELECT clause and can be of maximum 30 characters long. The table aliases should be meaningful. We rewrite the above query as:

SQL>Select ename, e.deptno, dname From emp e, dept d Where e.deptno = d.deptno;

Cartesian Join   When the join condition is omitted, the result is the Cartesian join of two or more tables in which all combinations of rows will be displayed. All the rows of the first table are joined to all rows of the second table. This kind of join tends to generate a large number of rows, as it involves no condition. For example, if the first table has five records and it is joined to the second table, which has three rows, then the result is a table consisting of fifteen records. This join is useful in finding all the possible combination of rows from different tables. This join does not require the tables to have common column between them.  

Syntax:  Select columnname1, columnname2……… From tablename1, tablename2…;  Example:  SQL>Select ename, dname from emp,dept;  

Outer Join   While using the equi join we have seen that if there exists certain records in one table which do not have corresponding values in the second, then those rows will not be selected. We can forcefully select such rows by using the outer join symbol (+). The corresponding rows for those columns will have NULL values .The outer join symbol is placed on the side of the join that is deficient in information. This operator has the effect of creating one or more null rows, to which one or more rows from the no deficient table can be joined. For example, to write a query that performs an outer join of tables A and B and returns all rows from A, apply the outer-join operator (+) to all columns of B in the join condition. For all rows in A that have no matching rows in B, the query returns NULL values for the columns in B.  

Syntax:  Select table1.column, table2.column,………. From table1, table2 Where table1.column (+) = table2.column; Or Select table1.column, table2.column,…………… From table1, table2 Where table1.column = table2.column (+);  In the syntax table1.column = table2.column (+) either is the condition that joins the tables together. is the outer join symbol, which can be placed on side of the where clause condition.

Example In the emp table, no record of the employee belongs to the department 40. Therefore, in case of equi join, the row of department 40 from the dept table will not be displayed. In order to include that row in the output Outer join is used.   • Display the list of employees working in each department. Display the department information even if no employee belongs to that department.  

SQL>SELECT empno, ename, emp.deptno, dname, loc FROM emp, dept WHERE emp.deptno (+) = dept.deptno;

If the symbol (+) is placed on the other side of the equation then all the employee details with no corresponding department name and location, will be displayed with NULL values in DNAME and LOC column.

Rules to Place (+) operator   • The outer join symbol (+) cannot be on both sides. • We cannot “outer join” the same table to more than one other table in a single SELECT statement. • A condition involving an outer join may not use the IN operator or be linked to another condition by the OR operator.

Self Join   The self-join can be seen as a join of two copies of the same table. The table is not actually copied, but SQL performs the command as though it were. The syntax of command for joining a table to itself is almost the same as that for joining two different tables. In order to differentiate the column from one another aliases are used, since both the tables have the same name.  

♦ To list out the names of the manager with the employee record one will have to join EMP itself.

SQL>SELECT WORKER. Ename “Ename”, MANAGER.ename “Manager” FROM emp WORKER, emp MANAGER WHERE WORKER.mgr=MANAGER.empno;   Where WORKER and MANAGER are two aliases for the EMP table and acts as virtual tables.  

Nested Queries   SQL has ability to nest queries within one another. A subquery is a SELECT statement, which is nested within another SELECT statement. One can build powerful statements out of simple ones by using sub queries. The inner queries generate values, which are tested to tell the outer query. SQL first evaluates the nested query within the where clause. The return value of inner query is then substituted in the condition of the outer query. One can use the subquery with the number of SQL clauses. • • • Where clause Having clause From clause

There are certain rules, which are to be followed while writing the nested queries. The nested queries must be enclosed in the parenthesis and it must appear on the right side of the comparison operator. One cannot use the order by clause within the subquery, and if used, it should be used as the last clause with the main select statement. The subquery uses number of comparison operators, which falls into different categories, the single-row comparison operators (>, <,>=, <=, <>, =) and multiple row comparison operators (in, any, all). There are number of advantages of the nested queries. They allow the developer to build powerful commands out of simple ones. Sub queries can be very useful when you want to select rows from a table with a condition, which depends on the data from the table itself.  

A single–row subquery returns one row from the inner nested query. These type of subqueries uses single-row operators (>, <,>=, <=, <>, =). Example:   •List the employees belonging to the department of MILLER. In this query, if we analyze closely, we see that we do not know the number of department in which MILLER works. So, first we have to determine the number of department of MILLER and then we can find out the employees working in that department. Let’s, first write two separate queries and then we will combine them.  

•List the name of the employees who do the same job as that of an employee number 7369.

SQL>Select ename, job from emp 7369); Where job = (select job From emp Where empno =

•List the name and job of the employee who do the same job as empno 7369 and gets salary greater than the salary of empno 7876.   SQL>Select ename, job from emp Where job = (select job from emp Where empno = 7369) empno = 7876); And sal > (select sal from emp Where

Using GROUP functions in a subquery   Aggregate functions produce a single value for any number of rows. One can display data from a main query by using a group function in a subquery to return a single value.   Example: •List the name and salary of the employee who gets salary greater than the minimum salary in the employee table. SQL>Select ename, sal from emp where sal > (select min (sal) From emp);

•List the employee name and salary of the employee whose salary is greater than the average salary of employees whose hiredate is before 01-jan-81. SQL>Select ename, sal from emp where sal > (select avg (sal) from emp where hiredate < ‘01-jan-81 ‘);  

Using DISTINCT clause in subquery   Distinct clause is used in some cases to force a subquery to generate a single value.   Example: •List the details of the department whose manager’s empcode is 7698. SQL>Select * from dept From emp Where deptno = (select distinct deptno From emp Where mgr = ‘7698 ‘);

Problems with single-row subqueries   One common error with subqueries is more than one row returned for a single-row subquery.  SQL> Select empno, ename From emp Where sal = (select min(sal) from emp Group by deptno);   ERROR at line 2: ORA-01427: single-row subquery returns more than one row

Multiple-Row queries   Subqueries that return more than one row are called multiple row subqueries. We use a multiple-row operator, instead of a single-row operator, with a multiple-row subquery. The multiple-row operator accepts one or more values.

Using ANY Operator in Multiple-Row Subqueries  The ANY operator (and its synonym SOME operator) compares a value to each value returned by a subquery. •Display employees whose salary is less than any clerk and who are not clerks. The maximum salary that a clerk earns is Rs.1300. The SQL statement displays all the employees who are not clerks but earn less than Rs. 1300.  Here <ANY: means less than the maximum     >ANY: means more than the minimum =ANY: is equivalent to IN.

SQL> SELECT empno, ename, job FROM emp WHERE sal < ANY(SELECT sal FROM emp WHERE job=’CLERK’) AND job<>’CLERK’;

Using ALL Operator in Multiple-Row Subqueries  The ALL operator compares a value to every value returned by a subquery. • Display employee number and name whose salary is greater than the average salary of all the departments. The highest average salary of a department is Rs.2916.66, so the query returns those employees whose salary is greater than Rs.2916.66.  Here: >ALL: <ALL: means more than the maximum means less than the minimum

The NOT operator can be used with IN, ANY and ALL operators.

Using HAVING clause in subqueries There can be a HAVING clause within the subquery. The Oracle server executes the subquery and the results are returned into the having clause of the main query. These queries can use their own aggregate functions as long as they do not produce multiple values or use GROUP BY or HAVING themselves. List the job with highest average salary. SQL> Select job, avg (sal) From emp Group by job Having avg (sal) = (select max (avg (sal)) From emp Group by job);

Multiple-column Sub-queries  So far we have written single-row subqueries where only one column was compared in the WHERE clause or HAVING clause of the SELECT statement. If you want to compare two or more columns, we must write a compound WHERE clause using logical operators. Multiple-column subqueries enable us to combine duplicate WHERE conditions into a single WHERE clause.  Syntax:  SQL>SELECT column, column,……….. FROM table WHERE (column, column, ……..) IN (SELECT column, column,.. FROM table WHERE condition);

• Display the order id, product id and quantity of items in the item table that match both the product id and quantity of an item in order 605.   SQL> SELECT ordid, prodid,qty FROM item WHERE (prodid, qty) IN (SELECT prodid, qty FROM item WHERE ordid=605) AND ordid<>605;

Correlated Subqueries Oracle performs a correlated subquery when the subquery references a column from a table referred to in the parent statement. A correlated subquery is evaluated once for each row processed by the parent statement. The parent statement can be a SELECT, UPDATE, or DELETE statement. Select the highest-paid employee of each department. SQL> SELECT deptno, ename, sal FROM emp e1 WHERE sal = (SELECT MAX(sal) FROM emp WHERE deptno = e1.deptno) ORDER BY deptno;

Dno sal 10 500 10 300 20 100 20 300 30 400

Dno Sal 10 500 10 300 20 100 20 300 30 400

SQL> SELECT deptno, ename, sal FROM emp e1 WHERE sal = (SELECT MAX(sal) FROM emp WHERE e1.deptno = deptno) ORDER BY deptno;

Select the highest-paid employee of each department

• To display name of top five highest paid employees from emp table.   SQL>SELECT E.ENAME,E.SAL FROM EMP E WHERE 5> (SELECT COUNT(*) FROM EMP WHERE E.SAL<EMP.SAL) ORDER BY SAL DESC;

1 2 3 4 5 6

1000 2000 3000 4000 5000 6000

5 4 3 2 1 0

1 2 3 4 5 6

1000 2000 3000 4000 5000 6000


•Query to display name of five employees who are getting minimum pay from emp table SQL>SELECT E.ENAME,E.SAL FROM EMP E WHERE 5> (SELECT COUNT(*) FROM EMP WHERE E.SAL>EMP.SAL) ORDER BY SAL DESC

1 2 3 4 5 6

1000 2000 3000 4000 5000 6000

0 1 2 3 4 5

1 2 3 4 5 6

1000 2000 3000 4000 5000 6000


Special operators in Sub-queries   Some special operators used in subqueries are:   • • • •   EXISTS ANY SOME ALL

EXISTS Operator   The EXISTS operator is frequently used with correlated subqueries. It tests whether a value is there or not (NOT EXISTS ensure for non-existence of values). If the value exists it returns TRUE, if it does not then it returns FALSE. NOT EXISTS operator is more reliable if the subquery returns any NULL values.   Examples: •List all the employees who have at least one person reporting to them.  

ANY Operator   The ANY operator compares the lowest value from the set.   Examples: List the employee names whose salary is greater than the lowest salary of employee belonging to department number 20.

ALL Operator   In case of ALL operator the predicate is true if every value selected by the subquery satisfies the condition in the predicate of the outer query.   Example: •List the employee names whose salary is greater than the highest salary of all employees belonging to department number 20;

SQL> SELECT empno, ename, sal FROM emp WHERE sal>ALL job=’MANAGER’); (SELECT sal FROM emp WHERE

ROWNUM  For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on.  We can use ROWNUM to limit the number of rows returned by a query, as in this example returns first 10 records of emp table:  SELECT * FROM emp WHERE ROWNUM < 10;  If an ORDER BY clause follows ROWNUM only those records are ordered which are selected by rownum. SELECT empno,sal FROM emp WHERE ROWNUM <= 5 ORDER BY sal;  It will only order the first five records of the emp table on the basis of sal

For example, the following query returns the top 5 highest paid employees information.   SELECT * FROM (SELECT empno,sal FROM emp ORDER BY sal desc) WHERE ROWNUM <= 5;

Similarly the following query will display the 10 smallest employee numbers. This is sometimes referred to as a "top-N query":  SELECT * FROM (SELECT empno FROM emp ORDER BY empno) WHERE ROWNUM < 11;  In the above examples, the ROWNUM values are those of the top-level SELECT statement, so they are generated after the rows have already been ordered by SAL or EMPNO in the subquery.  

Conditions testing for ROWNUM values greater than a positive integer are always false. For example, this query returns no rows: SELECT * FROM emp WHERE ROWNUM > 1; The first row fetched is assigned a ROWNUM of 1 and makes the condition false. The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 and makes the condition false. All rows subsequently fail to satisfy the condition, so no rows are returned.   We can also use ROWNUM to assign unique values to each row of a table, as in this example:  UPDATE tabx SET col1 = ROWNUM;

Sign up to vote on this title
UsefulNot useful