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
- INNER
- CROSS
- STRAIGHT_JOIN
- LEFT [OUTER] JOIN
- NATURAL [LEFT [OUTER]] JOIN
- RIGHT [OUTER] JOIN
- NATURAL [RIGHT [OUTER]] JOIN
Oracle JOIN Keywords
- CROSS JOIN
- FULL OUTER JOIN
- INTERSECT
- MINUS
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