Assuming you're joining on columns with no duplicates, which is a very common case:

An inner join of A and B gives the result of A intersect B, i.e. the inner part of a Venn diagram intersection.

An outer join of A and B gives the results of A union B, i.e. the outer parts of a Venn diagram union.

**Examples**

Suppose you have two tables, with a single column each, and data as follows:

```
A B
- -
1 3
2 4
3 5
4 6
```

Note that (1,2) are unique to A, (3,4) are common, and (5,6) are unique to B.

**Inner join**

An inner join using either of the equivalent queries gives the intersection of the two tables, i.e. the two rows they have in common.

```
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
```

**Left outer join**

A left outer join will give all rows in A, plus any common rows in B.

```
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
```

**Right outer join**

A right outer join will give all rows in B, plus any common rows in A.

```
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
```

**Full outer join**

A full outer join will give you the union of A and B, i.e. all the rows in A and all the rows in B. If something in A doesn't have a corresponding datum in B, then the B portion is null, and vice versa.

```
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
```

`UNION`

removes duplicate records (where all columns in the results are the same), `UNION ALL`

does not.

There is a performance hit when using `UNION`

instead of `UNION ALL`

, since the database server must do additional work to remove the duplicate rows, but usually you do not want the duplicates (especially when developing reports).

To identify duplicates, records must be comparable types as well as compatible types. This will depend on the SQL system. For example the system may truncate all long text fields to make short text fields for comparison (MS Jet), or may refuse to compare binary fields (ORACLE)

### UNION Example:

```
SELECT 'foo' AS bar UNION SELECT 'foo' AS bar
```

**Result:**

```
+-----+
| bar |
+-----+
| foo |
+-----+
1 row in set (0.00 sec)
```

### UNION ALL example:

```
SELECT 'foo' AS bar UNION ALL SELECT 'foo' AS bar
```

**Result:**

```
+-----+
| bar |
+-----+
| foo |
| foo |
+-----+
2 rows in set (0.00 sec)
```

## Best Solution

Simple Example: Let's say you have a`Students`

table, and a`Lockers`

table. In SQL, the first table you specify in a join,`Students`

, is theLEFTtable, and the second one,`Lockers`

, is theRIGHTtable.Each student can be assigned to a locker, so there is a

`LockerNumber`

column in the`Student`

table. More than one student could potentially be in a single locker, but especially at the beginning of the school year, you may have some incoming students without lockers and some lockers that have no students assigned.For the sake of this example, let's say you have

100 students, 70 of which have lockers. You have a total of50 lockers, 40 of which have at least 1 student and 10 lockers have no student.`INNER JOIN`

is equivalent to "show me all students with lockers".Any students without lockers, or any lockers without students are missing.

Returns 70 rows`LEFT OUTER JOIN`

would be "show me all students, with their corresponding locker if they have one".This might be a general student list, or could be used to identify students with no locker.

Returns 100 rows`RIGHT OUTER JOIN`

would be "show me all lockers, and the students assigned to them if there are any".This could be used to identify lockers that have no students assigned, or lockers that have too many students.

Returns 80 rows(list of 70 students in the 40 lockers, plus the 10 lockers with no student)`FULL OUTER JOIN`

would be silly and probably not much use.Something like "

show me all students and all lockers, and match them up where you can"Returns 110 rows(all 100 students, including those without lockers. Plus the 10 lockers with no student)`CROSS JOIN`

is also fairly silly in this scenario.It doesn't use the linked

`lockernumber`

field in the students table, so you basically end up with a big giant list of every possible student-to-locker pairing, whether or not it actually exists.Returns 5000 rows(100 students x 50 lockers). Could be useful (with filtering) as a starting point to match up the new students with the empty lockers.