Join Formats

There are two available join formats, namely the original Oracle proprietary format and the recently introduced ANSI standard join format. Both of the two different formats provide equally good performance.

Oracle's Proprietary Format

SELECT { [ [schema.]table. | [alias.] ]
   { column | expression [, ... ] } | * } 
FROM [schema.]table [alias] [, …]
[ WHERE 
   [ [schema.]table.|alias.] { column | expression [(+)] }
      comparison condition
   [ [schema.]table.|alias.] { column | expression [(+)] }
   [ { AND | OR } [ NOT ] … ]
];

The Outer Join Operator (+)

The outer join operator is the (+) operator and appears on the side of the expression containing the data source or table which is deficient in information. Here is an example.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a, publication pl, edition e, publisher pu
WHERE pl.author_id = a.author_id
AND e.publication_id = pl.publication_id
AND pu.publisher_id = e.publisher_id;

The New ANSI Standard Format

SELECT { { [ [schema.]table.|alias.] { column | expression } [, … ] } | * }
FROM [schema.]table [alias]
[
     CROSS JOIN [schema.]table [alias]
   | NATURAL [ INNER | [ LEFT | RIGHT | FULL ] OUTER ]
	JOIN [schema.]table [alias]
   | {
         [ INNER | [ LEFT | RIGHT | FULL ] OUTER ] JOIN [schema.]table [alias]
         {    
              ON (column = column [ { AND | OR } [ NOT ] column = column ... ] )
            | USING (column [, column ... ]) 
         }
     }
]
[ WHERE ... ] [ ORDER BY ... ];

This is the same example as the previous one but using the ANSI standard join format.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a JOIN publication pl USING(author_id)
	JOIN edition e USING(publication_id)
		JOIN publisher pu USING (publisher_id);

The USING and ON Clauses

The USING and ON clauses are used exclusively in the ANSI standard join format in order to qualify column names to be joined on.

The USING Clause

The USING clause is used to join two tables where two tables have column names which are the same, where those columns do not have matching values in them. For instance in the ERD for the Books schema shown below the Author and Publisher tables both have NAME columns; the values in those two NAME columns are completely different and thus joining AUTHOR.NAME and PUBLISHER.NAME is completely meaningless. Again using the same example as before, note that the query has a NAME column on both the Author and Publisher tables.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a JOIN publication pl USING(author_id)
	JOIN edition e USING(publication_id)
		JOIN publisher pu USING (publisher_id);

The ON Clause

The ON clause is used to join two tables where join column names are different.

SELECT a.name, pl.title, ca.coauthor_id
FROM author a JOIN publication pl ON (pl.author_id = a.author_id)
	JOIN coauthor ca ON (ca.coauthor_id = a.author_id);

Types of Joins

Comparison Condition Joins

These joins rely on comparison conditions between expressions and are effectively a subset of most other join types.

Cross Join or Cartesian Product

A cross join merges all data selected from both tables into a single result set by matching every row in one table with every row in the other table. The number of rows returned is the product or multiplication of the number of rows in each table; thus Cartesian Product.

The queries below show 6 authors, 11 publications and a resulting cross join between the two of 66 rows.

SELECT COUNT(*) FROM author;

  COUNT(*)
----------
         6

SELECT COUNT(*) FROM publication;

  COUNT(*)
----------
        11

SELECT COUNT(*) FROM author CROSS JOIN publication;

  COUNT(*)
----------
        66

Natural, Inner Join or Intersection

A natural join combines rows from both tables using matching column names and column values. It provides the intersection of two row sets, the rows common to both sets.

In the following example the natural join will occur naturally on the column name common to both tables, the AUTHOR_ID column. Note how the AUTHOR_ID column is not retrieved with an alias qualifier.

SELECT author_id, a.name, pl.title
FROM author a NATURAL JOIN publication pl;

 AUTHOR_ID NAME                             TITLE
---------- -------------------------------- -----------------------------------
         2 James Blish                      Cities in Flight
         2 James Blish                      A Case of Conscience
         3 Isaac Azimov                     Foundation
         3 Isaac Azimov                     Second Foundation
         3 Isaac Azimov                     Foundation and Empire
         3 Isaac Azimov                     Foundation's Edge
         3 Isaac Azimov                     Prelude to Foundation
         6 William Shakespeare              The Complete Works of Shakespeare
         4 Larry Niven                      Lucifer's Hammer
         4 Larry Niven                      Footfall
         4 Larry Niven                      Ringworld

11 rows selected.

Outer Joins

Outer joins select rows from both tables as with a natural join but including rows from one or both tables that do not have matching rows in the other table. Missing values are replaced with nulls. A union can sometimes be used as a substitute for an outer join.

Left Outer Join

A left outer join includes all rows from the left table plus all matching rows from the right table. Column values from the right table are replaced with nulls when the matching right side row does not exist in the left side table.

From the previous natural join query there are four authors listed as having publications. There are a total of six authors in the database, two of which do not have publications.

SELECT * FROM author;

 AUTHOR_ID NAME
---------- --------------------------------
         1 Orson Scott Card
         2 James Blish
         3 Isaac Azimov
         4 Larry Niven
         5 Jerry Pournelle
         6 William Shakespeare

6 rows selected.

Let's use a left outer join to retrieve all authors and publications, regardless of the existenece of a publication. Note how this first query has no alias qualifiers since all column names are different and the same where required.

SELECT author_id, name, title
FROM author LEFT OUTER JOIN publication USING (author_id);

 AUTHOR_ID NAME                             TITLE
---------- -------------------------------- -------------------------------------
         2 James Blish                      Cities in Flight
         2 James Blish                      A Case of Conscience
         3 Isaac Azimov                     Foundation
         3 Isaac Azimov                     Second Foundation
         3 Isaac Azimov                     Foundation and Empire
         3 Isaac Azimov                     Foundation's Edge
         3 Isaac Azimov                     Prelude to Foundation
         6 William Shakespeare              The Complete Works of Shakespeare
         4 Larry Niven                      Lucifer's Hammer
         4 Larry Niven                      Footfall
         4 Larry Niven                      Ringworld
         5 Jerry Pournelle
         1 Orson Scott Card

13 rows selected.

This second query includes the use of alias qualifiers. The ON clause changes to the USING clause since now specific column names in specific tables must be qualified. The resulting query will be the same.

SELECT a.author_id, a.name, pl.title
FROM author a LEFT OUTER JOIN publication pl ON (a.author_id = pl.author_id);

Now using the Oracle proprietary format where the outer join operator (+) is placed in the side of the comparison condition which is deficient in information; the Publication table is the table missing rows.

SELECT a.author_id, a.name, pl.title
FROM author a, publication pl
WHERE a.author_id = pl.author_id(+);

 AUTHOR_ID NAME                             TITLE
---------- -------------------------------- ----------------------------------
         1 Orson Scott Card
         2 James Blish                      Cities in Flight
         2 James Blish                      A Case of Conscience
         3 Isaac Azimov                     Foundation
         3 Isaac Azimov                     Second Foundation
         3 Isaac Azimov                     Foundation and Empire
         3 Isaac Azimov                     Foundation's Edge
         3 Isaac Azimov                     Prelude to Foundation
         4 Larry Niven                      Lucifer's Hammer
         4 Larry Niven                      Footfall
         4 Larry Niven                      Ringworld
         5 Jerry Pournelle
         6 William Shakespeare              The Complete Works of Shakespeare

13 rows selected.

Right Outer Join

A right outer join includes all rows from the table on the right plus matching rows from the left table; the opposite of the left outer join.

The simplest method of showing the difference between a left and outer join is to use the opposite of the left outer join queries used in the previous examples, simply reversing the join orders.

SELECT author_id, name, title
FROM publication RIGHT OUTER JOIN author USING (author_id);

SELECT a.author_id, a.name, pl.title
FROM author a, publication pl
WHERE pl.author_id(+) = a.author_id;

Full Outer Join

A full outer join includes all rows from both tables, both matching and non-matching, with nulls replacing missing values. A full outer join not is the same as a Cartesian Product. Full outer joins are quite often as pointless to use as Cartesian Products and their use is likely to indicate data model problems.

SELECT author_id, name, title
FROM publication FULL OUTER JOIN author USING (author_id);

Self Join

A self join, sometimes called a fish hook join, simply joins a table to itself by matching rows in the same table to other rows or the same rows in the same table.

SELECT parent.name, child.name
FROM subject parent, subject child
WHERE child.parent_id = parent.subject_id;

NAME                             NAME
-------------------------------- --------------------------------
Non-Fiction                      Self Help
Non-Fiction                      Esoteric
Non-Fiction                      Metaphysics
Non-Fiction                      Computers
Fiction                          Science Fiction
Fiction                          Fantasy
Fiction                          Drama
Fiction                          Whodunnit
Fiction                          Suspense
Fiction                          Literature
Literature                       Poetry
Literature                       Victorian
Literature                       Shakespearian
Literature                       Modern American
Literature                       19th Century American
Fiction                          Subject name

16 rows selected.

Mutable and Complex Joins

A mutable join is a join of more than two tables. A complex join is a mutable join with added filtering. The more tables in a mutable complex join the worse the performance of the query is likely to be. The following query is a mutable join.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a, publication pl, edition e, publisher pu
WHERE pl.author_id = a.author_id
AND e.publication_id = pl.publication_id
AND pu.publisher_id = e.publisher_id;

This is the ANSI format of the same mutable join.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a JOIN publication pl USING(author_id)
	JOIN edition e USING(publication_id)
		JOIN publisher pu USING (publisher_id);

The next query is a complex join because it has more than two tables plus some filtering. Note how filtering is applied before any joins are executed; this will help to increase performance by reducing the number of rows joined.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a, publication pl, edition e, publisher pu
WHERE a.name LIKE '%a%'
AND pl.author_id = a.author_id
AND e.publication_id = pl.publication_id
AND pu.publisher_id = e.publisher_id;

This is the same complex join in ANSI format. Note how filtering with the WHERE clause is applied after all joins are completed; this is not how the Optimizer will execute this query - filtering will be applied first to reduce the number of rows joined.

SELECT a.name, pl.title, e.ISBN, pu.name
FROM author a JOIN publication pl USING(author_id)
	JOIN edition e USING(publication_id)
		JOIN publisher pu USING (publisher_id)
WHERE a.name LIKE '%a%';