1. Overview
An outer join extends the result of a simple join. An outer join returns all rows that satisfy the join condition and also returns some or all of those rows from one table for which no rows from the other satisfy the join condition.
An OUTER JOIN
in Oracle retrieves rows from two or more tables, including unmatched rows from one or both tables. This makes it useful when you want to retain all rows from one table while including only matching rows from the other table. Outer joins are particularly helpful in scenarios where you want to include data that may not have corresponding entries in the related table.
- To write a query that performs an outer join of tables A and B and returns all rows from A (a left outer join), use the
LEFT [OUTER] JOIN
syntax in theFROM
clause, or apply the outer join operator (+) to all columns of B in the join condition in theWHERE
clause. For all rows in A that have no matching rows in B, Oracle Database returns null for any select list expressions containing columns of B. - To write a query that performs an outer join of tables A and B and returns all rows from B (a right outer join), use the
RIGHT [OUTER] JOIN
syntax in theFROM
clause, or apply the outer join operator (+) to all columns of A in the join condition in theWHERE
clause. For all rows in B that have no matching rows in A, Oracle returns null for any select list expressions containing columns of A. - To write a query that performs an outer join and returns all rows from A and B, extended with nulls if they do not satisfy the join condition (a full outer join), use the
FULL [OUTER] JOIN
syntax in theFROM
clause. - You cannot compare a column with a subquery in the
WHERE
clause of any outer join, regardless which form you specify.
2. Types of outer joins
Oracle supports three types of outer joins:
- LEFT OUTER JOIN: Returns all rows from the left table and the matched rows from the right table. Unmatched rows from the right table are filled with
NULL
. - RIGHT OUTER JOIN: Returns all rows from the right table and the matched rows from the left table. Unmatched rows from the left table are filled with
NULL
. - FULL OUTER JOIN: Returns all rows when there is a match in either table, and unmatched rows from both tables are filled with
NULL
. Combines the results of aLEFT OUTER JOIN
and aRIGHT OUTER JOIN
. It includes:- Matched rows from both tables.
- Unmatched rows from the first table (filled with
NULL
for the second table’s columns). - Unmatched rows from the second table (filled with
NULL
for the first table’s columns).
- Useful when you need a comprehensive view of data, including all matches and non-matches between two tables.
3. Syntax of Outer Join
LEFT OUTER JOIN
SELECT column_list FROM table1 LEFT OUTER JOIN table2 ON table1.column_name = table2.column_name;
RIGHT OUTER JOIN
SELECT column_list FROM table1 RIGHT OUTER JOIN table2 ON table1.column_name = table2.column_name;
FULL OUTER JOIN
SELECT column_list FROM table1 FULL OUTER JOIN table2 ON table1.column_name = table2.column_name;
Syntax (Using + Operator)
In Oracle, the + operator can also be used to perform outer joins. This syntax is older but still widely supported.
LEFT OUTER JOIN Using +
SELECT column_list FROM table1, table2 WHERE table1.column_name = table2.column_name(+);
RIGHT OUTER JOIN Using +
SELECT column_list FROM table1, table2 WHERE table1.column_name(+) = table2.column_name;
4. Examples
We’ll use the following tables for this example.
Employee
+-------------+------------+-----------+---------------+
| EMPLOYEE_ID | FIRST_NAME | LAST_NAME | DEPARTMENT_ID |
+-------------+------------+-----------+---------------+
| 101 | John | Doe | 1 |
+-------------+------------+-----------+---------------+
| 102 | Jane | Smith | 2 |
+-------------+------------+-----------+---------------+
| 103 | Sam | Brown | 3 |
+-------------+------------+-----------+---------------+
| 104 | Sue | Green | 2 |
+-------------+------------+-----------+---------------+
| 105 | Tom | Day | 4 |
+-------------+------------+-----------+---------------+
Department
+---------------+-----------------+
| DEPARTMENT_ID | DEPARTMENT_NAME |
+---------------+-----------------+
| 1 | Human Resources |
+---------------+-----------------+
| 2 | Finance |
+---------------+-----------------+
| 3 | IT |
+---------------+-----------------+
| 5 | Sales |
+---------------+-----------------+
LEFT OUTER JOIN Example (ANSI Syntax)
Fetch all employees and their department names (including employees without a department):
SELECT e.employee_id, e.first_name, d.department_name FROM employee e LEFT OUTER JOIN department d ON e.department_id = d.department_id;
Output
+-------------+------------+-----------------+
| EMPLOYEE_ID | FIRST_NAME | DEPARTMENT_NAME |
+-------------+------------+-----------------+
| 101 | John | Human Resources |
+-------------+------------+-----------------+
| 102 | Jane | Finance |
+-------------+------------+-----------------+
| 104 | Sue | Finance |
+-------------+------------+-----------------+
| 103 | Sam | IT |
+-------------+------------+-----------------+
| 105 | Tom | (null) |
+-------------+------------+-----------------+
LEFT OUTER JOIN Example (Using + Operator)
SELECT e.employee_id, e.first_name, d.department_name FROM employee e, department d WHERE e.department_id = d.department_id(+);
Output will be the same as earlier.
RIGHT OUTER JOIN Example (ANSI Syntax)
Let us now change LEFT OUTER JOIN to RIGHT OUTER JOIN in previous example.
SELECT e.employee_id, e.first_name, d.department_name FROM employee e RIGHT OUTER JOIN department d ON e.department_id = d.department_id;
+-------------+------------+-----------------+
| EMPLOYEE_ID | FIRST_NAME | DEPARTMENT_NAME |
+-------------+------------+-----------------+
| 101 | John | Human Resources |
+-------------+------------+-----------------+
| 102 | Jane | Finance |
+-------------+------------+-----------------+
| 103 | Sam | IT |
+-------------+------------+-----------------+
| 104 | Sue | Finance |
+-------------+------------+-----------------+
| (null) | (null) | Sales |
+-------------+------------+-----------------+
As you can see, all departments are returned even with no employees.
Right outer join with + operator
SELECT e.employee_id, e.first_name, d.department_name FROM employee e, department d WHERE e.department_id(+) = d.department_id;
The output will still be the same.
5. Full Outer Join
SELECT e.employee_id, e.first_name, d.department_name FROM employee e FULL OUTER JOIN department d ON e.department_id = d.department_id;
+-------------+------------+-----------------+
| EMPLOYEE_ID | FIRST_NAME | DEPARTMENT_NAME |
+-------------+------------+-----------------+
| 101 | John | Human Resources |
+-------------+------------+-----------------+
| 102 | Jane | Finance |
+-------------+------------+-----------------+
| 103 | Sam | IT |
+-------------+------------+-----------------+
| 104 | Sue | Finance |
+-------------+------------+-----------------+
| 105 | Tom | (null) |
+-------------+------------+-----------------+
| (null) | (null) | Sales |
+-------------+------------+-----------------+
- You cannot specify the (+) operator in a query block that also contains
FROM
clause join syntax. - The (+) operator can appear only in the
WHERE
clause or, in the context of left-correlation (when specifying theTABLE
clause) in theFROM
clause, and can be applied only to a column of a table or view. - If A and B are joined by multiple join conditions, then you must use the (+) operator in all of these conditions. If you do not, then Oracle Database will return only the rows resulting from a simple join, but without a warning or error to advise you that you do not have the results of an outer join.
- The (+) operator does not produce an outer join if you specify one table in the outer query and the other table in an inner query.
- You cannot use the (+) operator to outer-join a table to itself, although self joins are valid. For example, the following statement is not valid:
SELECT employee_id, manager_id FROM employees WHERE employees.manager_id(+) = employees.employee_id;
However, the following self join is valid:
SELECT e1.employee_id, e1.manager_id, e2.employee_id FROM employees e1, employees e2 WHERE e1.manager_id(+) = e2.employee_id ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
- The (+) operator can be applied only to a column, not to an arbitrary expression. However, an arbitrary expression can contain one or more columns marked with the (+) operator.
- A
WHERE
condition containing the (+) operator cannot be combined with another condition using theOR
logical operator. - A
WHERE
condition cannot use theIN
comparison condition to compare a column marked with the (+) operator with an expression.