Joins,
Peter Komisar © Conestoga College version 1.2

reference: MySQL Reference Manual. MySQL Structured Query
Language(SQL) ,D.Geller, R. Roselius, Danielle Waleri, DDC Publi.
Core MySQL, Leon Atkinson, Prentice-Hall Publishing,
'Joins Note,
http://www.udel.edu/evelyn/SQL-Class2/SQLclass2_Join.html



Character Set Support

This is an interesting point which we might have covered
earlier. Better late than never. MySQL supports a large
number of the world's character sets. To see what is
supported the Show command is used as follows.


MySQL Character Set Support Example

mysql> show character set;

+----------+-----------------------------+---------------------+
| Charset | Description | Default collation |
+----------+-----------------------------+---------------------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci |
| dec8 | DEC West European | dec8_swedish_ci |
| cp850 | DOS West European | cp850_general_ci |
| hp8 | HP West European | hp8_english_ci |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci |
| latin1 | cp1252 West European | latin1_swedish_ci |
| latin2 | ISO 8859-2 Central European | latin2_general_ci |
| swe7 | 7bit Swedish | swe7_swedish_ci |
| ascii | US ASCII | ascii_general_ci |
| ujis | EUC-JP Japanese | ujis_japanese_ci |
| sjis | Shift-JIS Japanese | sjis_japanese_ci |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci |
| tis620 | TIS620 Thai | tis620_thai_ci |
| euckr | EUC-KR Korean | euckr_korean_ci |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci |
| greek | ISO 8859-7 Greek | greek_general_ci |
| cp1250 | Windows Central European | cp1250_general_ci |
| gbk | GBK Simplified Chinese | gbk_chinese_ci |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci |
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci |
| utf8 | UTF-8 Unicode | utf8_general_ci |
| ucs2 | UCS-2 Unicode | ucs2_general_ci |
| cp866 | DOS Russian | cp866_general_ci |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci |
| macce | Mac Central European | macce_general_ci |
| macroman | Mac West European | macroman_general_ci |
| cp852 | DOS Central European | cp852_general_ci |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci |
| cp1251 | Windows Cyrillic | cp1251_general_ci |
| cp1256 | Windows Arabic | cp1256_general_ci |
| cp1257 | Windows Baltic | cp1257_general_ci |
| binary | Binary pseudo charset | binary |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci |
+----------+-----------------------------+---------------------+

Sometimes these encoding will be used with File loads.
Notice the values that are used are listed in the first column.


Example

LOAD DATA INFILE "C:\\ONMgr.txt" INTO TABLE
mgr_contacts CHARACTER SET 'latin1';


JOINS

Joins offer the database programmer the ability to
retrieve data from a set of tables, filtering this data
according to a set of conditions.



Joins extend the use of the SELECT command.
Effectively, a SELECT is made across a set of tables.

It is in the FROM part of the SELECT where more than
one table may be specified.

Two parts of the statement can be used to create
JOINS. Expressions can be used in the FROM clause
or conditions can be specified in the WHERE clause.
Usually INNER JOINS can be easily implemented in
the WHERE clause where OUTER JOINS involve
the use of the FROM clause.


Setting Up for Some Examples

Let us create a table called 'Mgr_contacts' that stores
the values from store in 'MANAGER_ID'.


We could add primary keys, indexing defaults, not
nulls etc. however we won't at this time. Instead we
will just concentrate on JOINs on simple tables.



Example

CREATE TABLE mgr_contacts(
MANAGER_ID int(11),
NAME varchar (40),
STREET varchar(40),
CITY varchar(30),
PROVINCE char(2),
POSTAL_CODE char(6),
AREA_CODE char(3),
PHONE_NUMBER char(7)
);


Execution

mysql> CREATE TABLE mgr_contacts(
-> MANAGER_ID int(11),
-> NAME varchar (40),
-> STREET varchar(40),
-> CITY varchar(30),
-> PROVINCE char(2),
-> POSTAL_CODE char(6),
-> AREA_CODE char(3),
-> PHONE_NUMBER char(7)
-> );

Query OK, 0 rows affected (0.17 sec)

The new table is populated the long way with
a series of inserts.


Insert Statements

INSERT INTO mgr_contacts values(
1105,'Allen Jackson','41 Memorial Ave.','Orillia','ON','KOJ1K0','705','71
74448');

INSERT INTO mgr_contacts values(
1011,'Wally Chester','2044 Beverly St.','Aylmer','ON','L2J4T0','613','94
27456');

INSERT INTO mgr_contacts values(
2019,'Gordon Teasdale','21-B Jelly Ave.','Shelburne','ON','J9K1B0','519',
'9392565');

INSERT INTO mgr_contacts values(
2001,'Alison Kettle','101 Lakeshore Ave.','Meaford','ON','L1T2D8','705','
7675554');

INSERT INTO mgr_contacts values(
9001,'Maynard Whistle','1001 MacKenzie Ave.','Richmond Hill','ON','905','
4350701');

INSERT INTO mgr_contacts values(
-> 8786,'Wesley East','44 King St.W.','Hamilton','ON','H2T2W3','905','345234
3');


Following are some of the rows of the table with the
data entered so far. The managers do not always live
in the same cities as their stores. The last two of these
managers do not have stores at this time.

SELECTION ON the mgr_contacts Table after INSERTS


mysql> select manager_id,name,city, area_code, phone_number from mgr_contacts;

+------------+-----------------+-----------+-----------+--------------+
| manager_id | name            | city      | area_code | phone_number |
+------------+-----------------+-----------+-----------+--------------+
| 1011       | Wally Chester   | Aylmer    | 613       | 9427456      |
| 1012       | Betty Davis     | Toronto   | 416       | 6544078      |
| 1105       | Allen Jackson   | Orillia   | 705       | 7174448      |
| 2001       | Alison Kettle   | Meaford   | 705       | 7675554      |
| 2019       | Gordon Teasdale | Shelburne | 519       | 9392565      |
| 8786       | Wesley East     | Hamilton  | 905       | 3452343      |
| 7767       | Anwar Sudat     | Barrie    | 705       | 2457343      |
+------------+-----------------+-----------+-----------+--------------+

6 rows in set (0.00 sec)


JOIN Examples

Essentially a JOIN is a SELECT on more than one tables.
Consider a problem whose answer takes data from both
tables.  We would like to know individuals who are associated
with a store in one city but who lives in another city.

Example

SELECT DISTINCT mgr_contacts.name from mgr_contacts, store
where store.city !=mgr_contacts.city;


Execution

mysql> SELECT mgr_contacts.name from mgr_contacts, store
    -> where store.city=mgr_contacts.city;
+-------------+
| name        |
+-------------+
| Betty Davis |
| Betty Davis |
| Anwar Sudat |
+-------------+
3 rows in set (0.00 sec)

The DISTINCT keyword can hide duplications.


Execution


mysql> SELECT DISTINCT mgr_contacts.name from mgr_contacts, store

    -> where store.city=mgr_contacts.city;
+-------------+
| name        |
+-------------+
| Betty Davis |
| Anwar Sudat |
+-------------+
2 rows in set (0.00 sec)

In the following query, store number and manager ids
are taken from the store table, and names are taken
from the mgr_contact table based on equating the
manager id in each table.

These are the names of the managers in the mgr_contact
table that have manager_ids associated with stores.

Example

mysql> SELECT DISTINCT store.store_number,store.manager_id, mgr_contacts.name
    -> from store,mgr_contacts
    -> where mgr_contacts.manager_id=store.manager_id;

+--------------+------------+-----------------+
| store_number | manager_id | name            |
+--------------+------------+-----------------+
|         1009 |       1011 | Wally Chester   |
|         1010 |       1012 | Betty Davis     |
|         1012 |       1105 | Allen Jackson   |
|         1013 |       2019 | Gordon Teasdale |
+--------------+------------+-----------------+
4 rows in set (0.00 sec)


Notice we only entered managers from Ontario. We would
have all the store managers names if we had entered them
into our table.

INNER JOINS

The above example where a condition is used to
specified a value that is found in both tables is called
an 'inner join'.

"INNER JOIN and , (comma) are semantically equivalent
in the absence of a join condition.

The above statement could have been made explicitly
a JOIN as follows.

Example

SELECT DISTINCT store.store_number,store.manager_id,
mgr_contacts.name from store INNER JOIN mgr_contacts
ON mgr_contacts.manager_id=store.manager_id;

Example

mysql> SELECT DISTINCT store.store_number,store.manager_id,
    -> mgr_contacts.name from store INNER JOIN mgr_contacts
    -> ON mgr_contacts.manager_id=store.manager_id;

+--------------+------------+-----------------+
| store_number | manager_id | name            |
+--------------+------------+-----------------+
|         1009 |       1011 | Wally Chester   |
|         1010 |       1012 | Betty Davis     |
|         1012 |       1105 | Allen Jackson   |
|         1013 |       2019 | Gordon Teasdale |
+--------------+------------+-----------------+
4 rows in set (0.17 sec)



Different Types of Joins


Following are common JOIN types

The easiest way to visualize what JOINs due is to represent
them as Venn Diagrams.


The INNER JOIN

The Inner Join or common intersection is first represented.
(The square is an artifact of the rendering. The JOIN is the
overlapping area of the two circles.


INNER JOIN Depiction


+--------------------------+
| table 1                  |
|            +---------------------------+
|            |             |             |
+--------------------------+             |
             |                 table 2   |
             +---------------------------+ 


// the intersection or just matching rows  



In the database, an INNER JOIN is data that has been
selected that is present in both tables.  Only those rows
with columns that have values common to all tables are
selected.

 
The LEFT JOIN

The LEFT JOIN adds to the Intersection all the values
of the left table whether in common or not.  Effectively
this is all the rows of the left table.


LEFT JOIN Depiction


+--------------------------+

| table 1                  |
|            +---------------------------+
|            |             |             |
+--------------------------+             |
             |                 table 2   |
             +---------------------------+ 

// intersect plus non-matching left rows



The RIGHT JOIN

The RIGHT JOIN adds all the rows of the right
table plus the intersection of the two tables. 
Effectively this is all the rows of the right table.


RIGHT JOIN Depiction

+--------------------------+
| table 1                  |
|            +---------------------------+
|            |             |             |
+--------------------------+             |
             |                 table 2   |
             +---------------------------+


// intersect plus non-matching right rows


The FULL OUTER JOIN

The FULL OUTER JOIN is both left and right joins.
A full outer join selects all the rows that are in common
as well as those rows of the left table that are not in
common and the rows in the right table that is not in
common. Effectively this is the UNION of the two tables
or everything. 

There is a distinguishing feature in the full outer join.
When no matching rows exist on the left side NULLs
are set on the right. The converse also exists where
no matching rows exist fro rows on the right side,
a NULL values are set for the left.


Full Outer Depiction


+--------------------------+

| table 1                  |
|            +---------------------------+
|            |             |             |
+--------------------------+             |
             |                 table 2   |
             +---------------------------+

// intersect plus non-matching left and right rows



CROSS JOINS

A CROSS JOIN select all the possible combinations of 
rows and columns from two or more tables, generating
the Cartesian product. A Cross Join may generate a
huge amount of data in what is not a very useful result
set. 
    
JOIN Keywords   

ANSI specifies the use of:
MySQL and other databases add other keywords.
For instance MySQL includes the following keywords
used within the context of SELECT on more than one
table

Other JOIN keywords

Oracle JOIN Keywords

The following examples should show how many of these
keywords may be used.

A Script to Test Different Types of Joins

CREATE TABLE IF NOT EXISTS left_T(
   hand integer,
   data varchar(8)
   );

CREATE TABLE IF NOT EXISTS right_T(
   hand integer,
   data varchar(8)
   );

Insert into left_T (hand, data) values
 (1, 'Lxxxxxxx'),
 (2, 'LLxxxxxx'),
 (3, 'LLLxxxxx'),
 (4, 'LLLLxxxx'),
 (5, 'LLLLLxxx'),
 (6, 'LLLLLLxx'),
 (7, 'LLLLLLLx'),
 (8, 'LLLLLLLL'),
 (19,'LxLxxxxx'),
 (31,'LxLLxxxx')
 ;

Insert into right_T (hand, data) values
 (1, 'Ryyyyyyy'),
 (2, 'RRyyyyyy'),
 (3, 'RRRyyyyy'),
 (4, 'RRRRyyyy'),
 (5, 'RRRRRyyy'),
 (6, 'RRRRRRyy'),
 (7, 'RRRRRRRy'),
 (8, 'RRRRRRRR'),
 (91,'RyRyyyyy'),
 (13,'RyRRyyyy')
 ;

Select * from left_T;
Select * from right_T;


Cut and past at MySQL Command
Line.


Execution

mysql> CREATE TABLE IF NOT EXISTS left
    ->    hand integer,
    ->    data varchar(8)
    ->    );
Query OK, 0 rows affected (0.06 sec)

mysql>
mysql> CREATE TABLE IF NOT EXISTS righ
    ->    hand integer,
    ->    data varchar(8)
    ->    );
Query OK, 0 rows affected (0.06 sec)

mysql>
mysql> Insert into left_T (hand, data)
    ->  (1, 'Lxxxxxxx'),
    ->  (2, 'LLxxxxxx'),
    ->  (3, 'LLLxxxxx'),
    ->  (4, 'LLLLxxxx'),
    ->  (5, 'LLLLLxxx'),
    ->  (6, 'LLLLLLxx'),
    ->  (7, 'LLLLLLLx'),
    ->  (8, 'LLLLLLLL'),
    ->  (19,'LxLxxxxx'),
    ->  (31,'LxLLxxxx')
    ->  ;
Query OK, 10 rows affected (0.02 sec)
Records: 10  Duplicates: 0  Warnings:

mysql>
mysql>
mysql>
mysql> Insert into right_T (hand, data
    ->  (1, 'Ryyyyyyy'),
    ->  (2, 'RRyyyyyy'),
    ->  (3, 'RRRyyyyy'),
    ->  (4, 'RRRRyyyy'),
    ->  (5, 'RRRRRyyy'),
    ->  (6, 'RRRRRRyy'),
    ->  (7, 'RRRRRRRy'),
    ->  (8, 'RRRRRRRR'),
    ->  (91,'RyRyyyyy'),
    ->  (13,'RyRRyyyy')
    ->  ;
Query OK, 10 rows affected (0.02 sec)
Records: 10  Duplicates: 0  Warnings:

mysql>
mysql> Select * from left_T;
+------+----------+
| hand | data     |
+------+----------+
|    1 | Lxxxxxxx |
|    2 | LLxxxxxx |
|    3 | LLLxxxxx |
|    4 | LLLLxxxx |
|    5 | LLLLLxxx |
|    6 | LLLLLLxx |
|    7 | LLLLLLLx |
|    8 | LLLLLLLL |
|   19 | LxLxxxxx |
|   31 | LxLLxxxx |
+------+----------+
10 rows in set (0.00 sec)

mysql> Select * from right_T;

+------+----------+
| hand | data     |
+------+----------+
|    1 | Ryyyyyyy |
|    2 | RRyyyyyy |
|    3 | RRRyyyyy |
|    4 | RRRRyyyy |
|    5 | RRRRRyyy |
|    6 | RRRRRRyy |
|    7 | RRRRRRRy |
|    8 | RRRRRRRR |
|   91 | RyRyyyyy |
|   13 | RyRRyyyy |
+------+----------+
10 rows in set (0.00 sec)


Same Column Names


When using more than one table that
have same named columns, it is necessary
to qualify the name of the column with the
table name. Otherwise the database finds
the referencing 'ambiguous. This is evident
in all the following examples.



CROSS JOIN EXAMPLE


If we select data from both tables with no qualifiers
we get a CROSS JOIN. A cross join is the Cartesian
product where each row is selected against every
row of the other table. 

In our example there are ten rows in each table
so expect and do get a result set of 100 rows.


Cross Join Statement

Select left_T.hand, left_T.data, right_T.hand,right_T.data
from left_T,right_T;

Following is the execution. While truncated, enough
of the data is presented to show the pattern.


Execution

mysql> Select left_T.hand, left_T.data, right_T.hand,right_T.data
    -> from left_T,right_T;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    1 | Ryyyyyyy |
|    3 | LLLxxxxx |    1 | Ryyyyyyy |
|    4 | LLLLxxxx |    1 | Ryyyyyyy |
|    5 | LLLLLxxx |    1 | Ryyyyyyy |
|    6 | LLLLLLxx |    1 | Ryyyyyyy |
|    7 | LLLLLLLx |    1 | Ryyyyyyy |
|    8 | LLLLLLLL |    1 | Ryyyyyyy |
|   19 | LxLxxxxx |    1 | Ryyyyyyy |
|   31 | LxLLxxxx |    1 | Ryyyyyyy |
|    1 | Lxxxxxxx |    2 | RRyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    2 | RRyyyyyy |
|    4 | LLLLxxxx |    2 | RRyyyyyy |
|    5 | LLLLLxxx |    2 | RRyyyyyy |
|    6 | LLLLLLxx |    2 | RRyyyyyy |
|    7 | LLLLLLLx |    2 | RRyyyyyy |
|    8 | LLLLLLLL |    2 | RRyyyyyy |
|   19 | LxLxxxxx |    2 | RRyyyyyy |
|   31 | LxLLxxxx |    2 | RRyyyyyy |
|    1 | Lxxxxxxx |    3 | RRRyyyyy |
|    2 | LLxxxxxx |    3 | RRRyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    3 | RRRyyyyy |
|    5 | LLLLLxxx |    3 | RRRyyyyy |
|    6 | LLLLLLxx |    3 | RRRyyyyy |
|    7 | LLLLLLLx |    3 | RRRyyyyy |
|    8 | LLLLLLLL |    3 | RRRyyyyy |
|   19 | LxLxxxxx |    3 | RRRyyyyy |
|   31 | LxLLxxxx |    3 | RRRyyyyy |
// middle part of the result set is deleted for economy in the note
|    1 | Lxxxxxxx |   13 | RyRRyyyy |
|    2 | LLxxxxxx |   13 | RyRRyyyy |
|    3 | LLLxxxxx |   13 | RyRRyyyy |
|    4 | LLLLxxxx |   13 | RyRRyyyy |
|    5 | LLLLLxxx |   13 | RyRRyyyy |
|    6 | LLLLLLxx |   13 | RyRRyyyy |
|    7 | LLLLLLLx |   13 | RyRRyyyy |
|    8 | LLLLLLLL |   13 | RyRRyyyy |
|   19 | LxLxxxxx |   13 | RyRRyyyy |
|   31 | LxLLxxxx |   13 | RyRRyyyy |
+------+----------+------+----------+
100 rows in set (0.00 sec)


INNER JOIN


This is the commonest form of JOIN and is the one
we used in our introductory example. Usually JOINs
are based on exact matches between column values
taken from the different tables. These sets deriving
from exact matches are called 'equi-joins'.

We extend the CROSS JOIN to include the condition
where column values are equated.

Notice that the two rows in each table with non-matching
column values are excluded from the result set. This is
the intersection of the two data sets based on each tables
'hand' column values.


Example

SELECT left_T.hand, left_T.data,
right_T.hand,right_T.data
FROM     left_T,right_T
WHERE  left_T.hand=right_T.hand;

Execution

mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM   left_T,right_T
    -> WHERE left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
+------+----------+------+----------+
8 rows in set (0.00 sec)

// non matching column values are not included in the
// intersection


An inner join on the data column should yield
an empty intersection as is shown in the following
example.


Example & Execution

mysql> Select left_T.hand, left_T.data, right_T.hand,right_T.data
    -> from left_T,right_T where left_T.data=right_T.data;
Empty set (0.00 sec)

As mentioned earlier, the implicit inner join can
be notated in explicit form.

 Example

SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
FROM left_T INNER JOIN right_T
ON left_T.hand=right_T.hand;


Execution

mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T INNER JOIN right_T
    -> ON left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
+------+----------+------+----------+
8 rows in set (0.00 sec)

We can use the same notation to describe other
possible joins.

The OUTER JOIN


The OUTER essentially returns the union of all
the data in the tables as is shown in the following
example. Described differently, it is the matching
rows from the two tables, together with rows from
the all tables that do not match.

Database Variations

Different databases have different syntax for the
OUTER JOIN.  Oracles outer join is the same
as an inner join except it has a ( + ) notation
appended to the final column specified in the
equality condition.

Oracle

O'Reilly Example of an Oracle Full Outer Join Statement 
http://www.oreillynet.com/pub/a/network/2002/04/23/fulljoin.html

select p.part_id, s.supplier_name
from part p, supplier s
where p.supplier_id = s.supplier_id (+);


Informix


Informix uses the keyword 'OUTER' as is shown
in the following statement fragment.


Example of an Informix Statement  Fragment


FROM  . . . . . OUTER


Sybase and MS SQL Server


Sybase SQL Server and MS SQL Server
use short forms similar to Oracle, instead adding
an asterisk, preceding the equality symbol.


Example of an Sybase / MSSQL Statement  Fragment


. . . .
WHERE x.a *= y.a;


MySQL Doesn't Do OUTER JOINs

Perhaps surprisingly, perhaps not MySQL doesn't
do full outer joins. This may not be surprising in light
of the fact that it does supply a UNION statement
that effectively supplies the distinct values of a full
outer join. We will show this example after exampling
the left and right joins.

Example


THE LEFT OUTER JOIN

Notice in the left outer join, the values of the
intersection are supplied plus the values

that do not match from the right table.

Those values from the right table have NULL
values substituted for non-matching column
values.

// in MySQL the OUTER Keyword for left
// and right joins is optional and can be
// reduced to just 'LEFT JOIN'


Example


SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
FROM left_T LEFT OUTER JOIN right_T

ON left_T.hand=right_T.hand;



mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T LEFT OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
|   19 | LxLxxxxx | NULL | NULL     |
|   31 | LxLLxxxx | NULL | NULL     |
+------+----------+------+----------+
10 rows in set (0.14 sec)


THE RIGHT OUTER JOIN

Conversely, in the right outer join the values of
the intersection are supplied plus the values
that do not match from the right table.

This time the rows from the right table that
do not have matches in the left table show
NULL values for the left table column values.


Example


SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
FROM left_T RIGHT  OUTER JOIN right_T

ON left_T.hand=right_T.hand;



Execution


mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T RIGHT OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
| NULL | NULL     |   91 | RyRyyyyy |
| NULL | NULL     |   13 | RyRRyyyy |
+------+----------+------+----------+
10 rows in set (0.00 sec)



MySQL Equivalent of a FULL OUTER JOIN

Using the UNION.


We can use the UNION keyword to create a
union of left and right outer joins, effectively
creating a full outer join. There are probably
shorter ways to notate this, however it is very
clear what is happening in this example.

Notice that in the result set both sets of non-
matching rows from both tables are represented.

Example

SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
FROM left_T LEFT OUTER JOIN right_T
ON left_T.hand=right_T.hand

UNION

SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
FROM left_T RIGHT  OUTER JOIN right_T
ON left_T.hand=right_T.hand;

// that was all one statement!

Execution

mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T LEFT OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand
    ->
    -> UNION
    ->
    -> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T RIGHT  OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
|   19 | LxLxxxxx | NULL | NULL     |
|   31 | LxLLxxxx | NULL | NULL     |
| NULL | NULL     |   91 | RyRyyyyy |
| NULL | NULL     |   13 | RyRRyyyy |
+------+----------+------+----------+
12 rows in set (0.00 sec)


UNION ALL Gives ALL including Duplicates


mysql> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T LEFT OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand
    ->
    -> UNION ALL
    ->
    -> SELECT left_T.hand, left_T.data, right_T.hand,right_T.data
    -> FROM left_T RIGHT  OUTER JOIN right_T
    -> ON left_T.hand=right_T.hand;

+------+----------+------+----------+
| hand | data     | hand | data     |
+------+----------+------+----------+
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
|   19 | LxLxxxxx | NULL | NULL     |
|   31 | LxLLxxxx | NULL | NULL     |
|    1 | Lxxxxxxx |    1 | Ryyyyyyy |
|    2 | LLxxxxxx |    2 | RRyyyyyy |
|    3 | LLLxxxxx |    3 | RRRyyyyy |
|    4 | LLLLxxxx |    4 | RRRRyyyy |
|    5 | LLLLLxxx |    5 | RRRRRyyy |
|    6 | LLLLLLxx |    6 | RRRRRRyy |
|    7 | LLLLLLLx |    7 | RRRRRRRy |
|    8 | LLLLLLLL |    8 | RRRRRRRR |
| NULL | NULL     |   91 | RyRyyyyy |
| NULL | NULL     |   13 | RyRRyyyy |
+------+----------+------+----------+
20 rows in set (0.00 sec)


Other Sorts of JOINS 

There are three other JOINs that are described
briefly here, the SELF, MINUS and NATURAL
JOINS.



SELF JOIN 

There is a SELF JOIN where an alias is given to
a table and then the table is joined on the alias.
This may be useful for applying compound filtering
techniques to a table.

In the following example, the table bird is given two
names, (highlighted). These two aliases are then
used to represent the one table twice, as two
separate entities.


Example
// from http://www.java2s.com/Code/SQL/Join/Selfjoin.htm

mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
    ->        FROM bird AS p1, bird AS p2
    ->        WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';
+-----------+------+----------+------+---------+
| name      | sex  | name     | sex  | species |
+-----------+------+----------+------+---------+
| BlueBird1 | f    | RedBird1 | m    | Bus     |
| BlueBird1 | f    | RedBird3 | m    | Bus     |
| BlueBird1 | f    | RedBird4 | m    | Bus     |
+-----------+------+----------+------+---------+
3 rows in set (0.04 sec)


MINUS JOIN

There is a MINUS JOIN that is like a LEFT or
OUTER JOIN except it leaves out the intersection
part. Some databases like Oracle define a Minus
command.


Diagram of a Minus Join


+--------------------------+

| table 1                  |
|            +---------------------------+
|            |             |             |
+--------------------------+             |
             |                 table 2   |
             +---------------------------+ 

// like a left or right join however leaving out the
// interesection


Following is an Oracle command example from
'Tech on the Net'.

Example
// http://www.techonthenet.com/sql/minus.php


SELECT field1, field2, . field_n
FROM  tables
MINUS
SELECT field1, field2, . field_n
from tables;


The USING KEYWORD


Another notation that may be used with JOINS
in MySQL involves the USING keyword.

Example

SELECT * FROM left_T LEFT JOIN right_T USING (hand);

Execution

mysql> SELECT * FROM left_T LEFT JOIN right_T USING (hand);

+------+----------+----------+
| hand | data     | data     |
+------+----------+----------+
|    1 | Lxxxxxxx | Ryyyyyyy |
|    2 | LLxxxxxx | RRyyyyyy |
|    3 | LLLxxxxx | RRRyyyyy |
|    4 | LLLLxxxx | RRRRyyyy |
|    5 | LLLLLxxx | RRRRRyyy |
|    6 | LLLLLLxx | RRRRRRyy |
|    7 | LLLLLLLx | RRRRRRRy |
|    8 | LLLLLLLL | RRRRRRRR |
|   19 | LxLxxxxx | NULL     |
|   31 | LxLLxxxx | NULL     |
+------+----------+----------+
10 rows in set (0.01 sec)


The Natural Join in MySQL  // just for reference

The Natural Keyword in MySQL is used in
place of
USING to mean all matching columns
are selected.

As an example the following is an equivalent
form of the above statement.


mysql> SELECT * FROM left_T NATURAL LEFT JOIN right_T;

+------+----------+
| hand | data     |
+------+----------+
|    1 | Lxxxxxxx |
|    2 | LLxxxxxx |
|    3 | LLLxxxxx |
|    4 | LLLLxxxx |
|    5 | LLLLLxxx |
|    6 | LLLLLLxx |
|    7 | LLLLLLLx |
|    8 | LLLLLLLL |
|   19 | LxLxxxxx |
|   31 | LxLLxxxx |
+------+----------+
10 rows in set (0.00 sec)

Multiple JOINs

It should be stated that JOINS may be applied
to more than two tables. Investigating JOINs
on three or more tables is left to the reader.


Assignment


Create two tables, one called 'A' and one
called 'B'.  Create an  Integer column called
'numeral' and  a varchar column limited to 20
characters called word.  Populate the  word
column of table A with words starting with the
letter 'a'.Populate the  word column of table B
with words starting with the letter 'b'.

Use unique values in the numeral column where
7 of the numeric values are common to both tables.

Demonstrate the following joins on the tables.
Where needed use the numeral column values
in the conditional clauses.

a ) CROSS JOIN
// screen shot the first and last 5 values of the result set
b ) INNER JOIN
c ) LEFT OUTER JOIN
d ) RIGHT OUTER JOIN
e ) OUTER JOIN  // in MySQL use a UNION