Three table join with joins other than INNER JOIN - sql

I am learning SQL and am trying to learn JOINs this week.
I have gotten to the level where I can do three table joins, similar to a lot of examples I've seen. I'm still trying to figure out the tiny details of how things work. All the examples I've seen of three table joins use INNER JOINS only. What about LEFT and RIGHT JOINs? Do you ever use these in three table joins? What would it mean?
SELECT ~some columns~ FROM ~table name~
LEFT JOIN ~table 2~ ON ~criteria~
INNER JOIN ~table 3~ ON ~criteria~
or
SELECT ~some columns~ FROM ~table name~
INNER JOIN ~table 2~ ON ~criteria~
LEFT JOIN ~table 3~ ON ~criteria~
or
SELECT ~some columns~ FROM ~table name~
LEFT JOIN ~table 2~ ON ~criteria~
LEFT JOIN ~table 3~ ON ~criteria~
or
???
Just trying to explore the space as much as possible

Yes, I do use all three of those JOINs, although I tend to stick to using just LEFT (OUTER) JOINs instead of inter-mixing LEFT and RIGHT JOINs. I also use FULL OUTER JOINs and CROSS JOINs.
In summary, an INNER JOIN restricts the resultset only to those records satisfied by the JOIN condition. Consider the following tables
EDIT: I've renamed the Table names and prefix them with # so that Table Variables can be used for anyone reading this answer and wanting to experiment.
If you'd also like to experiment with this in the browser, I've set this all up on SQL Fiddle too;
#Table1
id | name
---------
1 | One
2 | Two
3 | Three
4 | Four
#Table2
id | name
---------
1 | Partridge
2 | Turtle Doves
3 | French Hens
5 | Gold Rings
SQL code
DECLARE #Table1 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))
INSERT INTO #Table1 VALUES(1, 'One');
INSERT INTO #Table1 VALUES(2, 'Two');
INSERT INTO #Table1 VALUES(3, 'Three');
INSERT INTO #Table1 VALUES(4, 'Four');
DECLARE #Table2 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))
INSERT INTO #Table2 VALUES(1, 'Partridge');
INSERT INTO #Table2 VALUES(2, 'Turtle Doves');
INSERT INTO #Table2 VALUES(3, 'French Hens');
INSERT INTO #Table2 VALUES(5, 'Gold Rings');
An INNER JOIN SQL Statement, joined on the id field
SELECT
t1.id,
t1.name,
t2.name
FROM
#Table1 t1
INNER JOIN
#Table2 t2
ON
t1.id = t2.id
Results in
id | name | name
----------------
1 | One | Partridge
2 | Two | Turtle Doves
3 | Three| French Hens
A LEFT JOIN will return a resultset with all records from the table on the left hand side of the join (if you were to write out the statement as a one liner, the table that appears first) and fields from the table on the right side of the join that match the join expression and are included in the SELECT clause. Missing details will be populated with NULL
SELECT
t1.id,
t1.name,
t2.name
FROM
#Table1 t1
LEFT JOIN
#Table2 t2
ON
t1.id = t2.id
Results in
id | name | name
----------------
1 | One | Partridge
2 | Two | Turtle Doves
3 | Three| French Hens
4 | Four | NULL
A RIGHT JOIN is the same logic as a LEFT JOIN but will return all records from the right-hand side of the join and fields from the left side that match the join expression and are included in the SELECT clause.
SELECT
t1.id,
t1.name,
t2.name
FROM
#Table1 t1
RIGHT JOIN
#Table2 t2
ON
t1.id = t2.id
Results in
id | name | name
----------------
1 | One | Partridge
2 | Two | Turtle Doves
3 | Three| French Hens
NULL| NULL| Gold Rings
Of course, there is also the FULL OUTER JOIN, which includes records from both joined tables and populates any missing details with NULL.
SELECT
t1.id,
t1.name,
t2.name
FROM
#Table1 t1
FULL OUTER JOIN
#Table2 t2
ON
t1.id = t2.id
Results in
id | name | name
----------------
1 | One | Partridge
2 | Two | Turtle Doves
3 | Three| French Hens
4 | Four | NULL
NULL| NULL| Gold Rings
And a CROSS JOIN (also known as a CARTESIAN PRODUCT), which is simply the product of cross applying fields in the SELECT statement from one table with the fields in the SELECT statement from the other table. Notice that there is no join expression in a CROSS JOIN
SELECT
t1.id,
t1.name,
t2.name
FROM
#Table1 t1
CROSS JOIN
#Table2 t2
Results in
id | name | name
------------------
1 | One | Partridge
2 | Two | Partridge
3 | Three | Partridge
4 | Four | Partridge
1 | One | Turtle Doves
2 | Two | Turtle Doves
3 | Three | Turtle Doves
4 | Four | Turtle Doves
1 | One | French Hens
2 | Two | French Hens
3 | Three | French Hens
4 | Four | French Hens
1 | One | Gold Rings
2 | Two | Gold Rings
3 | Three | Gold Rings
4 | Four | Gold Rings
EDIT:
Imagine there is now a Table3
#Table3
id | name
---------
2 | Prime 1
3 | Prime 2
5 | Prime 3
The SQL code
DECLARE #Table3 TABLE (id INT PRIMARY KEY CLUSTERED, [name] VARCHAR(25))
INSERT INTO #Table3 VALUES(2, 'Prime 1');
INSERT INTO #Table3 VALUES(3, 'Prime 2');
INSERT INTO #Table3 VALUES(5, 'Prime 3');
Now all three tables joined with INNER JOINS
SELECT
t1.id,
t1.name,
t2.name,
t3.name
FROM
#Table1 t1
INNER JOIN
#Table2 t2
ON
t1.id = t2.id
INNER JOIN
#Table3 t3
ON
t1.id = t3.id
Results in
id | name | name | name
-------------------------------
2 | Two | Turtle Doves | Prime 1
3 | Three| French Hens | Prime 2
It might help to understand this result by thinking that records with id 2 and 3 are the only ones common to all 3 tables and are also the field we are joining each table on.
Now all three with LEFT JOINS
SELECT
t1.id,
t1.name,
t2.name,
t3.name
FROM
#Table1 t1
LEFT JOIN
#Table2 t2
ON
t1.id = t2.id
LEFT JOIN
#Table3 t3
ON
t1.id = t3.id
Results in
id | name | name | name
-------------------------------
1 | One | Partridge | NULL
2 | Two | Turtle Doves | Prime 1
3 | Three| French Hens | Prime 2
4 | Four | NULL | NULL
Joel's answer is a good explanation for explaining this resultset (Table1 is the base/origin table).
Now with a INNER JOIN and a LEFT JOIN
SELECT
t1.id,
t1.name,
t2.name,
t3.name
FROM
#Table1 t1
INNER JOIN
#Table2 t2
ON
t1.id = t2.id
LEFT JOIN
#Table3 t3
ON
t1.id = t3.id
Results in
id | name | name | name
-------------------------------
1 | One | Partridge | NULL
2 | Two | Turtle Doves | Prime 1
3 | Three| French Hens | Prime 2
Although we do not know the order in which the query optimiser will perform the operations, we will look at this query from top to bottom to understand the resultset. The INNER JOIN on ids between Table1 and Table2 will restrict the resultset to only those records satisfied by the join condition i.e. the three rows that we saw in the very first example. This temporary resultset will then be LEFT JOINed to Table3 on ids between Table1 and Tables; There are records in Table3 with id 2 and 3, but not id 1, so t3.name field will have details in for 2 and 3 but not 1.

Joins are just ways of combining tables. Joining three tables is no different than joining 2... or 200. You can mix and match INNER, [LEFT/RIGHT/FULL] OUTER, and even CROSS joins as much as you want. The only difference is which results are kept: INNER joins only keep rows where both sides match the expression. OUTER joins pick an "origin" table depending on the LEFT/RIGHT/FULL specification, always keep all rows from the origin table, and supply NULL values for rows from the other side that don't match the expression. CROSS joins return all possible combinations of both sides.
The trick is that because you're working with declarative code rather than more-familiar iterative, the temptation is to try to think of it as if everything happens at once. When you do that, you try to wrap your head around the entire query and it can get confusing.
Instead, you want to think of it as if the joins happen in order, from the first table listed to the last. This actually is not how it works, because the query optimizer can re-order things to make them run faster. But it makes building the query easier for the developer.
So with three tables, you start with your base table, then join in the values you need from the next table, and the next, and so on, just like adding lines of code to a function to produce the required output.
As for using the different join types, I've used all the different types I listed here: INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER, and CROSS. But most of those you only need to use occasionally. INNER JOIN and LEFT JOIN will cover probably 95% or more of what you want to do.
Now let's talk about performance. Often times the order you list tables is dictated to you: you start from TableA and you need to list TableB first in order to have access to columns required to join in TableC. But sometimes both TableB and TableC only depend on TableA, and you could list them in either order. When that happens the query optimizer will usually pick the best order for you, but sometimes it doesn't know how. Even if it did, it helps to have a good system for listing tables so you can always look at a query and know that it's "right".
With that in mind, you should think of a query in terms of the working set currently in memory as the query builds. When you start with TableA, the database looks at all the columns from TableA in the select list or anywhere else (like WHERE or ORDER BY clauses, or potential indexes) in the query, factors in relevant conditions from the WHERE clause, and loads the smallest portion of that table into memory that it can get away with. It does this for each table in turn, always loading as little as possible. And that's the key: you want to keep this working set as small as possible for as long as possible.
So, going back to our three-table join, we want to list the tables in the order that will keep the working set smaller for longer. This means listing the smaller table above the larger one. Another good rule of thumb is that INNER joins tend to shrink result sets, while OUTER joins, tend to grow result sets, and so you want to list your INNER joins first. However, this is not a requirement for a query to work, nor is it always true; sometimes the reverse can happen as well.
Finally, I want to point out again that this isn't how it really works. The query optimizer and execution plans are a very complex topic, and there are lots of tricks the database can take that break this model from time to time. It's just one model that you as a developer can use to help understand what the server is doing and help you write better queries.

Selecting from three tables is no different from selecting from only two (or as many as a hundred, though that would be a fairly ugly query to read).
For EACH join you write, having INNER indicates that you only want rows that successfully join those two tables together. If other tables were joined earlier in the query, those results are now completely irrelevant, except to the extent your own join conditions call on them.
For example:
SELECT person.*
FROM person
LEFT JOIN vehicle ON (person.person_id = vehicle.owner_id)
LEFT JOIN house ON (person.person_id = house.owner_id)
Here I want a list of all people, and (if available) all the vehicles and houses they own.
Alternatively:
SELECT person.*
FROM person
INNER JOIN vehicle ON (person.person_id = vehicle.owner_id)
LEFT JOIN house ON (person.person_id = house.owner_id)
Here I want all people who own vehicles (they must own a vehicle to get results in my query), and (if available) all the houses they own).
Each join is completely separate here.
Of course, by varying what you put in the ON clause, you can make joins interrelate tables any way you want.

This really depends on what you are doing. I've written many 3+ table queries that will have an outer join in them. It just depends on the data you are querying and what you are trying to follow.
The same general logic applies when selecting the join type when you have multiples as with single join queries.

For the sake of this example, lets say we have a table "employees" with an ID, NAME and MANAGER_ID fields.
Here is a simple query:
SELECT E.ID, E.NAME, M.NAME AS MANAGER
FROM EMPLOYEES E
JOIN EMPLOYEE M ON E.MANAGER_ID = M.ID
This will return all of the employees, with their manager name. But what happens for the boss? he who has no manager? A database null would actually prevent that row from returning as it could not find a matching record to join on. Thus you would use an OUTER join (left or right depending on how your write the query).
The same logic would hold for writing a query with 2+n joins. If you are possibly going to have rows that don't have matches in your join clause, and want those rows to come back (albeit with nulls), then you are golden.

Read this great article on outer joins by a well known expert Terry Purcell
also a great write up by Plamen Ratchev

On some sql engines there's an issue where you're joining a using left join.
If you join A->B->C and the row in B doesn't exist then the join column from B is NULL.
A few I've used require that the join from B->C must be a left join if the join from A->B is a left join.
This is ok
select a.*, b.*, c.*
from a
left join b on b.id = a.id
left join c on c.id = b.id
this is not
select a.*, b.*, c.*
from a
left join b on b.id = a.id
inner join c on c.id = b.id

For the sake of completeness and standard evangelics, I'll chime in with the ansi-92 nested join syntax:
select t1.*
,t2.*
,t3.*
from table1 t1
left outer join (
table2 t2 left outer join table3 t3 on (t2.b = t3.b)
) on (t1.a = t2.a)
Your SQL engine of choice may optimize for them.

Related

Can you help me with understanding the terms of the INNER JOIN ON [duplicate]

Also, how do LEFT OUTER JOIN, RIGHT OUTER JOIN, and FULL OUTER JOIN fit in?
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
The Venn diagrams don't really do it for me.
They don't show any distinction between a cross join and an inner join, for example, or more generally show any distinction between different types of join predicate or provide a framework for reasoning about how they will operate.
There is no substitute for understanding the logical processing and it is relatively straightforward to grasp anyway.
Imagine a cross join.
Evaluate the on clause against all rows from step 1 keeping those where the predicate evaluates to true
(For outer joins only) add back in any outer rows that were lost in step 2.
(NB: In practice the query optimiser may find more efficient ways of executing the query than the purely logical description above but the final result must be the same)
I'll start off with an animated version of a full outer join. Further explanation follows.
Explanation
Source Tables
First start with a CROSS JOIN (AKA Cartesian Product). This does not have an ON clause and simply returns every combination of rows from the two tables.
SELECT A.Colour, B.Colour FROM A CROSS JOIN B
Inner and Outer joins have an "ON" clause predicate.
Inner Join. Evaluate the condition in the "ON" clause for all rows in the cross join result. If true return the joined row. Otherwise discard it.
Left Outer Join. Same as inner join then for any rows in the left table that did not match anything output these with NULL values for the right table columns.
Right Outer Join. Same as inner join then for any rows in the right table that did not match anything output these with NULL values for the left table columns.
Full Outer Join. Same as inner join then preserve left non matched rows as in left outer join and right non matching rows as per right outer join.
Some examples
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour = B.Colour
The above is the classic equi join.
Animated Version
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN ('Green','Blue')
The inner join condition need not necessarily be an equality condition and it need not reference columns from both (or even either) of the tables. Evaluating A.Colour NOT IN ('Green','Blue') on each row of the cross join returns.
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON 1 =1
The join condition evaluates to true for all rows in the cross join result so this is just the same as a cross join. I won't repeat the picture of the 16 rows again.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour
Outer Joins are logically evaluated in the same way as inner joins except that if a row from the left table (for a left join) does not join with any rows from the right hand table at all it is preserved in the result with NULL values for the right hand columns.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL
This simply restricts the previous result to only return the rows where B.Colour IS NULL. In this particular case these will be the rows that were preserved as they had no match in the right hand table and the query returns the single red row not matched in table B. This is known as an anti semi join.
It is important to select a column for the IS NULL test that is either not nullable or for which the join condition ensures that any NULL values will be excluded in order for this pattern to work correctly and avoid just bringing back rows which happen to have a NULL value for that column in addition to the un matched rows.
SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour
Right outer joins act similarly to left outer joins except they preserve non matching rows from the right table and null extend the left hand columns.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON A.Colour = B.Colour
Full outer joins combine the behaviour of left and right joins and preserve the non matching rows from both the left and the right tables.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON 1 = 0
No rows in the cross join match the 1=0 predicate. All rows from both sides are preserved using normal outer join rules with NULL in the columns from the table on the other side.
SELECT COALESCE(A.Colour, B.Colour) AS Colour FROM A FULL OUTER JOIN B ON 1 = 0
With a minor amend to the preceding query one could simulate a UNION ALL of the two tables.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour = 'Green'
Note that the WHERE clause (if present) logically runs after the join. One common error is to perform a left outer join and then include a WHERE clause with a condition on the right table that ends up excluding the non matching rows. The above ends up performing the outer join...
... And then the "Where" clause runs. NULL= 'Green' does not evaluate to true so the row preserved by the outer join ends up discarded (along with the blue one) effectively converting the join back to an inner one.
If the intention was to include only rows from B where Colour is Green and all rows from A regardless the correct syntax would be
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour AND B.Colour = 'Green'
SQL Fiddle
See these examples run live at SQLFiddle.com.
Joins are used to combine the data from two tables, with the result being a new, temporary table. Joins are performed based on something called a predicate, which specifies the condition to use in order to perform a join. The difference between an inner join and an outer join is that an inner join will return only the rows that actually match based on the join predicate.
For eg- Lets consider Employee and Location table:
Employee
EmpID
EmpName
13
Jason
8
Alex
3
Ram
17
Babu
25
Johnson
Location
EmpID
EmpLoc
13
San Jose
8
Los Angeles
3
Pune, India
17
Chennai, India
39
Bangalore, India
Inner Join:-
Inner join creates a new result table by combining column values of two tables (Employee and Location) based upon the join-predicate. The query compares each row of Employee with each row of Location to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied by matching non-NULL values, column values for each matched pair of rows of Employee and Location are combined into a result row.
Here’s what the SQL for an inner join will look like:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Now, here is what the result of running that SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
Outer Join:-
An outer join does not require each record in the two joined tables to have a matching record. The joined table retains each record—even if no other matching record exists. Outer joins subdivide further into left outer joins and right outer joins, depending on which table's rows are retained (left or right).
Left Outer Join:-
The result of a left outer join (or simply left join) for tables Employee and Location always contains all records of the "left" table (Employee), even if the join-condition does not find any matching record in the "right" table (Location).
Here is what the SQL for a left outer join would look like, using the tables above:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Now, here is what the result of running this SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
Note how while Johnson has no entry in the employee location table, he is still included in the results but the location fields are nulled.
Right Outer Join:-
A right outer join (or right join) closely resembles a left outer join, except with the treatment of the tables reversed. Every row from the "right" table (Location) will appear in the joined table at least once. If no matching row from the "left" table (Employee) exists, NULL will appear in columns from Employee for those records that have no match in Location.
This is what the SQL looks like:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Using the tables above, we can show what the result set of a right outer join would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
NULL
NULL
39
Bangalore, India
Note how while there are no employees listed as working in Bangalore, it is still included in the results with the employee fields nulled out.
Full Outer Joins:-
Full Outer Join or Full Join is to retain the nonmatching information by including nonmatching rows in the results of a join, use a full outer join. It includes all rows from both tables, regardless of whether or not the other table has a matching value.
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
NULL
NULL
39
Bangalore, India
MySQL 8.0 Reference Manual - Join Syntax
Oracle Join operations
Inner Join
Retrieve the matched rows only, that is, A intersect B.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Left Outer Join
Select all records from the first table, and any records in the second
table that match the joined keys.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Full Outer Join
Select all records from the second table, and any records in the first
table that match the joined keys.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
References
Inner and outer joins SQL examples and the Join block
SQL: JOINS
In simple words:
An inner join retrieve the matched rows only.
Whereas an outer join retrieve the matched rows from one table and all rows in other table ....the result depends on which one you are using:
Left: Matched rows in the right table and all rows in the left table
Right: Matched rows in the left table and all rows in the right table or
Full: All rows in all tables. It doesn't matter if there is a match or not
A inner join only shows rows if there is a matching record on the other (right) side of the join.
A (left) outer join shows rows for each record on the left hand side, even if there are no matching rows on the other (right) side of the join. If there is no matching row, the columns for the other (right) side would show NULLs.
Inner joins require that a record with a related ID exist in the joined table.
Outer joins will return records for the left side even if nothing exists for the right side.
For instance, you have an Orders and an OrderDetails table. They are related by an "OrderID".
Orders
OrderID
CustomerName
OrderDetails
OrderDetailID
OrderID
ProductName
Qty
Price
The request
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
will only return Orders that also have something in the OrderDetails table.
If you change it to OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
then it will return records from the Orders table even if they have no OrderDetails records.
You can use this to find Orders that do not have any OrderDetails indicating a possible orphaned order by adding a where clause like WHERE OrderDetails.OrderID IS NULL.
In simple words :
Inner join -> Take ONLY common records from parent and child tables WHERE primary key of Parent table matches Foreign key in Child table.
Left join ->
pseudo code
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Right join : Exactly opposite of left join . Put name of table in LEFT JOIN at right side in Right join , you get same output as LEFT JOIN.
Outer join : Show all records in Both tables No matter what. If records in Left table are not matching to right table based on Primary , Forieign key , use NULL value as result of join .
Example :
Lets assume now for 2 tables
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Here , employees table is Master table , phone_numbers_employees is child table(it contains emp_id as foreign key which connects employee.id so its child table.)
Inner joins
Take the records of 2 tables ONLY IF Primary key of employees table(its id) matches Foreign key of Child table phone_numbers_employees(emp_id).
So query would be :
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Here take only matching rows on primary key = foreign key as explained above.Here non matching rows on primary key = foreign key are skipped as result of join.
Left joins :
Left join retains all rows of the left table, regardless of whether there is a row that matches on the right table.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Outer joins :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Diagramatically it looks like :
You use INNER JOIN to return all rows from both tables where there is a match. i.e. In the resulting table all the rows and columns will have values.
In OUTER JOIN the resulting table may have empty columns. Outer join may be either LEFT or RIGHT.
LEFT OUTER JOIN returns all the rows from the first table, even if there are no matches in the second table.
RIGHT OUTER JOIN returns all the rows from the second table, even if there are no matches in the first table.
INNER JOIN requires there is at least a match in comparing the two tables. For example, table A and table B which implies A ٨ B (A intersection B).
LEFT OUTER JOIN and LEFT JOIN are the same. It gives all the records matching in both tables and all possibilities of the left table.
Similarly, RIGHT OUTER JOIN and RIGHT JOIN are the same. It gives all the records matching in both tables and all possibilities of the right table.
FULL JOIN is the combination of LEFT OUTER JOIN and RIGHT OUTER JOIN without duplication.
The answer is in the meaning of each one, so in the results.
Note :
In SQLite there is no RIGHT OUTER JOIN or FULL OUTER JOIN.
And also in MySQL there is no FULL OUTER JOIN.
My answer is based on above Note.
When you have two tables like these:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN :
You can have all of those tables data with CROSS JOIN or just with , like this:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN :
When you want to add a filter to above results based on a relation like table1.id = table2.id you can use INNER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
LEFT [OUTER] JOIN :
When you want to have all rows of one of tables in the above result -with same relation- you can use LEFT JOIN:
(For RIGHT JOIN just change place of tables)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN :
When you also want to have all rows of the other table in your results you can use FULL OUTER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Well, as your need you choose each one that covers your need ;).
Inner join.
A join is combining the rows from two tables. An inner join attempts to match up the two tables based on the criteria you specify in the query, and only returns the rows that match. If a row from the first table in the join matches two rows in the second table, then two rows will be returned in the results. If there’s a row in the first table that doesn’t match a row in the second, it’s not returned; likewise, if there’s a row in the second table that doesn’t match a row in the first, it’s not returned.
Outer Join.
A left join attempts to find match up the rows from the first table to rows in the second table. If it can’t find a match, it will return the columns from the first table and leave the columns from the second table blank (null).
INNER JOIN most typical join for two or more tables.
It returns data match on both table ON primarykey and forignkey relation.
OUTER JOIN is same as INNER JOIN, but it also include NULL data on ResultSet.
LEFT JOIN = INNER JOIN + Unmatched data of left table with Null match on right table.
RIGHT JOIN = INNER JOIN + Unmatched data of right table with Null match on left table.
FULL JOIN = INNER JOIN + Unmatched data on both right and left tables with Null matches.
Self join is not a keyword in SQL, when a table references data in itself knows as self join. Using INNER JOIN and OUTER JOIN we can write self join queries.
For example:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
I don't see much details about performance and optimizer in the other answers.
Sometimes it is good to know that only INNER JOIN is associative which means the optimizer has the most option to play with it. It can reorder the join order to make it faster keeping the same result. The optimizer can use the most join modes.
Generally it is a good practice to try to use INNER JOIN instead of the different kind of joins. (Of course if it is possible considering the expected result set.)
There are a couple of good examples and explanation here about this strange associative behavior:
Are left outer joins associative?
Does the join order matter in SQL?
Having criticized the much-loved red-shaded Venn diagram, I thought it only fair to post my own attempt.
Although #Martin Smith's answer is the best of this bunch by a long way, his only shows the key column from each table, whereas I think ideally non-key columns should also be shown.
The best I could do in the half hour allowed, I still don't think it adequately shows that the nulls are there due to absence of key values in TableB or that OUTER JOIN is actually a union rather than a join:
The precise algorithm for INNER JOIN, LEFT/RIGHT OUTER JOIN are as following:
Take each row from the first table: a
Consider all rows from second table beside it: (a, b[i])
Evaluate the ON ... clause against each pair: ON( a, b[i] ) = true/false?
When the condition evaluates to true, return that combined row (a, b[i]).
When reach end of second table without any match, and this is an Outer Join then return a (virtual) pair using Null for all columns of other table: (a, Null) for LEFT outer join or (Null, b) for RIGHT outer join. This is to ensure all rows of first table exists in final results.
Note: the condition specified in ON clause could be anything, it is not required to use Primary Keys (and you don't need to always refer to Columns from both tables)! For example:
... ON T1.title = T2.title AND T1.version < T2.version ( => see this post as a sample usage: Select only rows with max value on a column)
... ON T1.y IS NULL
... ON 1 = 0 (just as sample)
Note: Left Join = Left Outer Join, Right Join = Right Outer Join.
Simplest Definitions
Inner Join: Returns matched records from both tables.
Full Outer Join: Returns matched and unmatched records from both tables with null for unmatched records from Both Tables.
Left Outer Join: Returns matched and unmatched records only from table on Left Side.
Right Outer Join: Returns matched and unmatched records only from table on Right Side.
In-Short
Matched + Left Unmatched + Right Unmatched = Full Outer Join
Matched + Left Unmatched = Left Outer Join
Matched + Right Unmatched = Right Outer Join
Matched = Inner Join
The General Idea
Please see the answer by Martin Smith for a better illustations and explanations of the different joins, including and especially differences between FULL OUTER JOIN, RIGHT OUTER JOIN and LEFT OUTER JOIN.
These two table form a basis for the representation of the JOINs below:
CROSS JOIN
SELECT *
FROM citizen
CROSS JOIN postalcode
The result will be the Cartesian products of all combinations. No JOIN condition required:
INNER JOIN
INNER JOIN is the same as simply: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
The result will be combinations that satisfies the required JOIN condition:
LEFT OUTER JOIN
LEFT OUTER JOIN is the same as LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
The result will be everything from citizen even if there are no matches in postalcode. Again a JOIN condition is required:
Data for playing
All examples have been run on an Oracle 18c. They're available at dbfiddle.uk which is also where screenshots of tables came from.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
Blurry boundaries when playing with JOIN and WHERE
CROSS JOIN
CROSS JOIN resulting in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Using CROSS JOIN to get the result of a LEFT OUTER JOIN requires tricks like adding in a NULL row. It's omitted.
INNER JOIN
INNER JOIN becomes a cartesian products. It's the same as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
This is where the inner join can really be seen as the cross join with results not matching the condition removed. Here none of the resulting rows are removed.
Using INNER JOIN to get the result of a LEFT OUTER JOIN also requires tricks. It's omitted.
LEFT OUTER JOIN
LEFT JOIN results in rows as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN results in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
The troubles with the Venn diagram
An image internet search on "sql join cross inner outer" will show a multitude of Venn diagrams. I used to have a printed copy of one on my desk. But there are issues with the representation.
Venn diagram are excellent for set theory, where an element can be in one or both sets. But for databases, an element in one "set" seem, to me, to be a row in a table, and therefore not also present in any other tables. There is no such thing as one row present in multiple tables. A row is unique to the table.
Self joins are a corner case where each element is in fact the same in both sets. But it's still not free of any of the issues below.
The set A represents the set on the left (the citizen table) and the set B is the set on the right (the postalcode table) in below discussion.
CROSS JOIN
Every element in both sets are matched with every element in the other set, meaning we need A amount of every B elements and B amount of every A elements to properly represent this Cartesian product. Set theory isn't made for multiple identical elements in a set, so I find Venn diagrams to properly represent it impractical/impossible. It doesn't seem that UNION fits at all.
The rows are distinct. The UNION is 7 rows in total. But they're incompatible for a common SQL results set. And this is not how a CROSS JOIN works at all:
Trying to represent it like this:
..but now it just looks like an INTERSECTION, which it's certainly not. Furthermore there's no element in the INTERSECTION that is actually in any of the two distinct sets. However, it looks very much like the searchable results similar to this:
For reference one searchable result for CROSS JOINs can be seen at Tutorialgateway. The INTERSECTION, just like this one, is empty.
INNER JOIN
The value of an element depends on the JOIN condition. It's possible to represent this under the condition that every row becomes unique to that condition. Meaning id=x is only true for one row. Once a row in table A (citizen) matches multiple rows in table B (postalcode) under the JOIN condition, the result has the same problems as the CROSS JOIN: The row needs to be represented multiple times, and the set theory isn't really made for that. Under the condition of uniqueness, the diagram could work though, but keep in mind that the JOIN condition determines the placement of an element in the diagram. Looking only at the values of the JOIN condition with the rest of the row just along for the ride:
This representation falls completely apart when using an INNER JOIN with a ON 1 = 1 condition making it into a CROSS JOIN.
With a self-JOIN, the rows are in fact idential elements in both tables, but representing the tables as both A and B isn't very suitable. For example a common self-JOIN condition that makes an element in A to be matching a different element in B is ON A.parent = B.child, making the match from A to B on seperate elements. From the examples that would be a SQL like this:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Meaning Smith is the leader of both Green and Jensen.
OUTER JOIN
Again the troubles begin when one row has multiple matches to rows in the other table. This is further complicated because the OUTER JOIN can be though of as to match the empty set. But in set theory the union of any set C and an empty set, is always just C. The empty set adds nothing. The representation of this LEFT OUTER JOIN is usually just showing all of A to illustrate that rows in A are selected regardless of whether there is a match or not from B. The "matching elements" however has the same problems as the illustration above. They depend on the condition. And the empty set seems to have wandered over to A:
WHERE clause - making sense
Finding all rows from a CROSS JOIN with Smith and postalcode on the Moon:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Now the Venn diagram isn't used to reflect the JOIN. It's used only for the WHERE clause:
..and that makes sense.
When INTERSECT and UNION makes sense
INTERSECT
As explained an INNER JOIN is not really an INTERSECT. However INTERSECTs can be used on results of seperate queries. Here a Venn diagram makes sense, because the elements from the seperate queries are in fact rows that either belonging to just one of the results or both. Intersect will obviously only return results where the row is present in both queries. This SQL will result in the same row as the one above WHERE, and the Venn diagram will also be the same:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
UNION
An OUTER JOIN is not a UNION. However UNION work under the same conditions as INTERSECT, resulting in a return of all results combining both SELECTs:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
which is equivalent to:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..and gives the result:
Also here a Venn diagram makes sense:
When it doesn't apply
An important note is that these only work when the structure of the results from the two SELECT's are the same, enabling a comparison or union. The results of these two will not enable that:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
..trying to combine the results with UNION gives a
ORA-01790: expression must have same datatype as corresponding expression
For further interest read Say NO to Venn Diagrams When Explaining JOINs and sql joins as venn diagram. Both also cover EXCEPT.
In Simple Terms,
1.INNER JOIN OR EQUI JOIN : Returns the resultset that matches only the condition in both the tables.
2.OUTER JOIN : Returns the resultset of all the values from both the tables even if there is condition match or not.
3.LEFT JOIN : Returns the resultset of all the values from left table and only rows that match the condition in right table.
4.RIGHT JOIN : Returns the resultset of all the values from right table and only rows that match the condition in left table.
5.FULL JOIN : Full Join and Full outer Join are same.
left join on returns inner join on rows union all unmatched left table rows extended by nulls.
right join on returns inner join on rows union all unmatched right table rows extended by nulls.
full join on returns inner join on rowsunion all unmatched left table rows extended by nulls union all unmatched right table rows extended by nulls.
outer is optional & has no effect.
(SQL Standard 2006 SQL/Foundation 7.7 Syntax Rules 1, General Rules 1 b, 3 c & d, 5 b.)
So don't outer join on until you know what underlying inner join on is involved.
Find out what rows inner join on returns:
CROSS JOIN vs INNER JOIN in SQL
That also explains why Venn(-like) diagrams are not helpful for inner vs outer join.
For more on why they are not helpful for joins generally:
Venn Diagram for Natural Join
1.Inner Join: Also called as Join. It returns the rows present in both the Left table, and right table only if there is a match. Otherwise, it returns zero records.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2.Full Outer Join: Also called as Full Join. It returns all the rows present in both the Left table, and right table.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3.Left Outer join: Or simply called as Left Join. It returns all the rows present in the Left table and matching rows from the right table (if any).
4.Right Outer Join: Also called as Right Join. It returns matching rows from the left table (if any), and all the rows present in the Right table.
Advantages of Joins
Executes faster.
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.
Left outer join - A left outer join will give all rows in A, plus any common rows in B.
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 versay
Joins are more easily explained with an example:
To simulate persons and emails stored in separate tables,
Table A and Table B are joined by Table_A.id = Table_B.name_id
Inner Join
Only matched ids' rows are shown.
Outer Joins
Matched ids and not matched rows for Table A are shown.
Matched ids and not matched rows for Table B are shown.
Matched ids and not matched rows from both Tables are shown.
Note: Full outer join is not available on MySQL
Consider below 2 tables:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Department
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Inner Join:
Mostly written as just JOIN in sql queries. It returns only the matching records between the tables.
Find out all employees and their department names:
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
As you see above, Jose is not printed from EMP in the output as it's dept_id 6 does not find a match in the Department table. Similarly, HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table.
So, INNER JOIN or just JOIN, returns only matching rows.
LEFT JOIN :
This returns all records from the LEFT table and only matching records from the RIGHT table.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
So, if you observe the above output, all records from the LEFT table(Emp) are printed with just matching records from RIGHT table.
HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table on dept_id.
So, LEFT JOIN returns ALL rows from Left table and only matching rows from RIGHT table.
Can also check DEMO here.
There are a lot of good answers here with very accurate relational algebra examples. Here is a very simplified answer that might be helpful for amateur or novice coders with SQL coding dilemmas.
Basically, more often than not, JOIN queries boil down to two cases:
For a SELECT of a subset of A data:
use INNER JOIN when the related B data you are looking for MUST exist per database design;
use LEFT JOIN when the related B data you are looking for MIGHT or MIGHT NOT exist per database design.
The difference between inner join and outer join is as follow:
Inner join is a join that combined tables based on matching tuples, whereas outer join is a join that combined table based on both matched and unmatched tuple.
Inner join merges matched row from two table in where unmatched row are omitted, whereas outer join merges rows from two tables and unmatched rows fill with null value.
Inner join is like an intersection operation, whereas outer join is like an union operation.
Inner join is two types, whereas outer join are three types.
outer join is faster than inner join.
A Demonstration
Setup
Hop into psql and create a tiny database of cats and humans.
You can just copy-paste this whole section.
CREATE DATABASE catdb;
\c catdb;
\pset null '[NULL]' -- how to display null values
CREATE TABLE humans (
name text primary key
);
CREATE TABLE cats (
human_name text references humans(name),
name text
);
INSERT INTO humans (name)
VALUES ('Abe'), ('Ann'), ('Ben'), ('Jen');
INSERT INTO cats (human_name, name)
VALUES
('Abe', 'Axel'),
(NULL, 'Bitty'),
('Jen', 'Jellybean'),
('Jen', 'Juniper');
Querying
Here's a query we'll run several times, changing [SOMETHING JOIN] to the various types to see the results.
SELECT
humans.name AS human_name,
cats.name AS cat_name
FROM humans
[SOMETHING JOIN] cats ON humans.name = cats.human_name
ORDER BY humans.name;
An INNER JOIN returns all human-cat pairs.
Any human without a cat or cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
A FULL OUTER JOIN returns all humans and all cats, with NULL if there is no match on either side.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
A LEFT OUTER JOIN returns all humans (the left table).
Any human without a cat gets a NULL in the cat_name column.
Any cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
A RIGHT OUTER JOIN returns all cats (the right table).
Any cat without a human gets a NULL in the human_name column.
Any human without a cat is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
INNER vs OUTER
You can see that while an INNER JOIN gets only matching pairs, each kind of OUTER join includes some items without a match.
However, the actual words INNER and OUTER do not need to appear in queries:
JOIN by itself implies INNER
LEFT JOIN, RIGHT JOIN and OUTER JOIN all imply OUTER
The "outer" and "inner" are just optional elements, you are just dealing with two (three) kinds of joins. Inner joins (or what is the default when using only "join") is a join where only the elements that match the criteria are present on both tables.
The "outer" joins are the same as the inner join plus the elements of the left or right table that didn't match, adding nulls on all columns for the other table.
The full join is the inner plus the right and left joins.
In summary, if we have table A like this
idA
ColumnTableA
idB
1
Jonh
1
2
Sarah
1
3
Clark
2
4
Barbie
NULL
And table B like this:
idB
ColumnTableB
1
Connor
2
Kent
3
Spock
The inner join:
from tableA join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
Left outer join:
from tableA left join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
Right outer join:
from tableA right join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
NULL
NULL
3
Spock
Full outer join:
from tableA full join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
NULL
NULL
3
Spock

SQL: Understanding how FULL OUTER JOIN works [duplicate]

Also, how do LEFT OUTER JOIN, RIGHT OUTER JOIN, and FULL OUTER JOIN fit in?
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
The Venn diagrams don't really do it for me.
They don't show any distinction between a cross join and an inner join, for example, or more generally show any distinction between different types of join predicate or provide a framework for reasoning about how they will operate.
There is no substitute for understanding the logical processing and it is relatively straightforward to grasp anyway.
Imagine a cross join.
Evaluate the on clause against all rows from step 1 keeping those where the predicate evaluates to true
(For outer joins only) add back in any outer rows that were lost in step 2.
(NB: In practice the query optimiser may find more efficient ways of executing the query than the purely logical description above but the final result must be the same)
I'll start off with an animated version of a full outer join. Further explanation follows.
Explanation
Source Tables
First start with a CROSS JOIN (AKA Cartesian Product). This does not have an ON clause and simply returns every combination of rows from the two tables.
SELECT A.Colour, B.Colour FROM A CROSS JOIN B
Inner and Outer joins have an "ON" clause predicate.
Inner Join. Evaluate the condition in the "ON" clause for all rows in the cross join result. If true return the joined row. Otherwise discard it.
Left Outer Join. Same as inner join then for any rows in the left table that did not match anything output these with NULL values for the right table columns.
Right Outer Join. Same as inner join then for any rows in the right table that did not match anything output these with NULL values for the left table columns.
Full Outer Join. Same as inner join then preserve left non matched rows as in left outer join and right non matching rows as per right outer join.
Some examples
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour = B.Colour
The above is the classic equi join.
Animated Version
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN ('Green','Blue')
The inner join condition need not necessarily be an equality condition and it need not reference columns from both (or even either) of the tables. Evaluating A.Colour NOT IN ('Green','Blue') on each row of the cross join returns.
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON 1 =1
The join condition evaluates to true for all rows in the cross join result so this is just the same as a cross join. I won't repeat the picture of the 16 rows again.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour
Outer Joins are logically evaluated in the same way as inner joins except that if a row from the left table (for a left join) does not join with any rows from the right hand table at all it is preserved in the result with NULL values for the right hand columns.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL
This simply restricts the previous result to only return the rows where B.Colour IS NULL. In this particular case these will be the rows that were preserved as they had no match in the right hand table and the query returns the single red row not matched in table B. This is known as an anti semi join.
It is important to select a column for the IS NULL test that is either not nullable or for which the join condition ensures that any NULL values will be excluded in order for this pattern to work correctly and avoid just bringing back rows which happen to have a NULL value for that column in addition to the un matched rows.
SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour
Right outer joins act similarly to left outer joins except they preserve non matching rows from the right table and null extend the left hand columns.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON A.Colour = B.Colour
Full outer joins combine the behaviour of left and right joins and preserve the non matching rows from both the left and the right tables.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON 1 = 0
No rows in the cross join match the 1=0 predicate. All rows from both sides are preserved using normal outer join rules with NULL in the columns from the table on the other side.
SELECT COALESCE(A.Colour, B.Colour) AS Colour FROM A FULL OUTER JOIN B ON 1 = 0
With a minor amend to the preceding query one could simulate a UNION ALL of the two tables.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour = 'Green'
Note that the WHERE clause (if present) logically runs after the join. One common error is to perform a left outer join and then include a WHERE clause with a condition on the right table that ends up excluding the non matching rows. The above ends up performing the outer join...
... And then the "Where" clause runs. NULL= 'Green' does not evaluate to true so the row preserved by the outer join ends up discarded (along with the blue one) effectively converting the join back to an inner one.
If the intention was to include only rows from B where Colour is Green and all rows from A regardless the correct syntax would be
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour AND B.Colour = 'Green'
SQL Fiddle
See these examples run live at SQLFiddle.com.
Joins are used to combine the data from two tables, with the result being a new, temporary table. Joins are performed based on something called a predicate, which specifies the condition to use in order to perform a join. The difference between an inner join and an outer join is that an inner join will return only the rows that actually match based on the join predicate.
For eg- Lets consider Employee and Location table:
Employee
EmpID
EmpName
13
Jason
8
Alex
3
Ram
17
Babu
25
Johnson
Location
EmpID
EmpLoc
13
San Jose
8
Los Angeles
3
Pune, India
17
Chennai, India
39
Bangalore, India
Inner Join:-
Inner join creates a new result table by combining column values of two tables (Employee and Location) based upon the join-predicate. The query compares each row of Employee with each row of Location to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied by matching non-NULL values, column values for each matched pair of rows of Employee and Location are combined into a result row.
Here’s what the SQL for an inner join will look like:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Now, here is what the result of running that SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
Outer Join:-
An outer join does not require each record in the two joined tables to have a matching record. The joined table retains each record—even if no other matching record exists. Outer joins subdivide further into left outer joins and right outer joins, depending on which table's rows are retained (left or right).
Left Outer Join:-
The result of a left outer join (or simply left join) for tables Employee and Location always contains all records of the "left" table (Employee), even if the join-condition does not find any matching record in the "right" table (Location).
Here is what the SQL for a left outer join would look like, using the tables above:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Now, here is what the result of running this SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
Note how while Johnson has no entry in the employee location table, he is still included in the results but the location fields are nulled.
Right Outer Join:-
A right outer join (or right join) closely resembles a left outer join, except with the treatment of the tables reversed. Every row from the "right" table (Location) will appear in the joined table at least once. If no matching row from the "left" table (Employee) exists, NULL will appear in columns from Employee for those records that have no match in Location.
This is what the SQL looks like:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Using the tables above, we can show what the result set of a right outer join would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
NULL
NULL
39
Bangalore, India
Note how while there are no employees listed as working in Bangalore, it is still included in the results with the employee fields nulled out.
Full Outer Joins:-
Full Outer Join or Full Join is to retain the nonmatching information by including nonmatching rows in the results of a join, use a full outer join. It includes all rows from both tables, regardless of whether or not the other table has a matching value.
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
NULL
NULL
39
Bangalore, India
MySQL 8.0 Reference Manual - Join Syntax
Oracle Join operations
Inner Join
Retrieve the matched rows only, that is, A intersect B.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Left Outer Join
Select all records from the first table, and any records in the second
table that match the joined keys.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Full Outer Join
Select all records from the second table, and any records in the first
table that match the joined keys.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
References
Inner and outer joins SQL examples and the Join block
SQL: JOINS
In simple words:
An inner join retrieve the matched rows only.
Whereas an outer join retrieve the matched rows from one table and all rows in other table ....the result depends on which one you are using:
Left: Matched rows in the right table and all rows in the left table
Right: Matched rows in the left table and all rows in the right table or
Full: All rows in all tables. It doesn't matter if there is a match or not
A inner join only shows rows if there is a matching record on the other (right) side of the join.
A (left) outer join shows rows for each record on the left hand side, even if there are no matching rows on the other (right) side of the join. If there is no matching row, the columns for the other (right) side would show NULLs.
Inner joins require that a record with a related ID exist in the joined table.
Outer joins will return records for the left side even if nothing exists for the right side.
For instance, you have an Orders and an OrderDetails table. They are related by an "OrderID".
Orders
OrderID
CustomerName
OrderDetails
OrderDetailID
OrderID
ProductName
Qty
Price
The request
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
will only return Orders that also have something in the OrderDetails table.
If you change it to OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
then it will return records from the Orders table even if they have no OrderDetails records.
You can use this to find Orders that do not have any OrderDetails indicating a possible orphaned order by adding a where clause like WHERE OrderDetails.OrderID IS NULL.
In simple words :
Inner join -> Take ONLY common records from parent and child tables WHERE primary key of Parent table matches Foreign key in Child table.
Left join ->
pseudo code
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Right join : Exactly opposite of left join . Put name of table in LEFT JOIN at right side in Right join , you get same output as LEFT JOIN.
Outer join : Show all records in Both tables No matter what. If records in Left table are not matching to right table based on Primary , Forieign key , use NULL value as result of join .
Example :
Lets assume now for 2 tables
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Here , employees table is Master table , phone_numbers_employees is child table(it contains emp_id as foreign key which connects employee.id so its child table.)
Inner joins
Take the records of 2 tables ONLY IF Primary key of employees table(its id) matches Foreign key of Child table phone_numbers_employees(emp_id).
So query would be :
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Here take only matching rows on primary key = foreign key as explained above.Here non matching rows on primary key = foreign key are skipped as result of join.
Left joins :
Left join retains all rows of the left table, regardless of whether there is a row that matches on the right table.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Outer joins :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Diagramatically it looks like :
You use INNER JOIN to return all rows from both tables where there is a match. i.e. In the resulting table all the rows and columns will have values.
In OUTER JOIN the resulting table may have empty columns. Outer join may be either LEFT or RIGHT.
LEFT OUTER JOIN returns all the rows from the first table, even if there are no matches in the second table.
RIGHT OUTER JOIN returns all the rows from the second table, even if there are no matches in the first table.
INNER JOIN requires there is at least a match in comparing the two tables. For example, table A and table B which implies A ٨ B (A intersection B).
LEFT OUTER JOIN and LEFT JOIN are the same. It gives all the records matching in both tables and all possibilities of the left table.
Similarly, RIGHT OUTER JOIN and RIGHT JOIN are the same. It gives all the records matching in both tables and all possibilities of the right table.
FULL JOIN is the combination of LEFT OUTER JOIN and RIGHT OUTER JOIN without duplication.
The answer is in the meaning of each one, so in the results.
Note :
In SQLite there is no RIGHT OUTER JOIN or FULL OUTER JOIN.
And also in MySQL there is no FULL OUTER JOIN.
My answer is based on above Note.
When you have two tables like these:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN :
You can have all of those tables data with CROSS JOIN or just with , like this:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN :
When you want to add a filter to above results based on a relation like table1.id = table2.id you can use INNER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
LEFT [OUTER] JOIN :
When you want to have all rows of one of tables in the above result -with same relation- you can use LEFT JOIN:
(For RIGHT JOIN just change place of tables)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN :
When you also want to have all rows of the other table in your results you can use FULL OUTER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Well, as your need you choose each one that covers your need ;).
Inner join.
A join is combining the rows from two tables. An inner join attempts to match up the two tables based on the criteria you specify in the query, and only returns the rows that match. If a row from the first table in the join matches two rows in the second table, then two rows will be returned in the results. If there’s a row in the first table that doesn’t match a row in the second, it’s not returned; likewise, if there’s a row in the second table that doesn’t match a row in the first, it’s not returned.
Outer Join.
A left join attempts to find match up the rows from the first table to rows in the second table. If it can’t find a match, it will return the columns from the first table and leave the columns from the second table blank (null).
INNER JOIN most typical join for two or more tables.
It returns data match on both table ON primarykey and forignkey relation.
OUTER JOIN is same as INNER JOIN, but it also include NULL data on ResultSet.
LEFT JOIN = INNER JOIN + Unmatched data of left table with Null match on right table.
RIGHT JOIN = INNER JOIN + Unmatched data of right table with Null match on left table.
FULL JOIN = INNER JOIN + Unmatched data on both right and left tables with Null matches.
Self join is not a keyword in SQL, when a table references data in itself knows as self join. Using INNER JOIN and OUTER JOIN we can write self join queries.
For example:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
I don't see much details about performance and optimizer in the other answers.
Sometimes it is good to know that only INNER JOIN is associative which means the optimizer has the most option to play with it. It can reorder the join order to make it faster keeping the same result. The optimizer can use the most join modes.
Generally it is a good practice to try to use INNER JOIN instead of the different kind of joins. (Of course if it is possible considering the expected result set.)
There are a couple of good examples and explanation here about this strange associative behavior:
Are left outer joins associative?
Does the join order matter in SQL?
Having criticized the much-loved red-shaded Venn diagram, I thought it only fair to post my own attempt.
Although #Martin Smith's answer is the best of this bunch by a long way, his only shows the key column from each table, whereas I think ideally non-key columns should also be shown.
The best I could do in the half hour allowed, I still don't think it adequately shows that the nulls are there due to absence of key values in TableB or that OUTER JOIN is actually a union rather than a join:
The precise algorithm for INNER JOIN, LEFT/RIGHT OUTER JOIN are as following:
Take each row from the first table: a
Consider all rows from second table beside it: (a, b[i])
Evaluate the ON ... clause against each pair: ON( a, b[i] ) = true/false?
When the condition evaluates to true, return that combined row (a, b[i]).
When reach end of second table without any match, and this is an Outer Join then return a (virtual) pair using Null for all columns of other table: (a, Null) for LEFT outer join or (Null, b) for RIGHT outer join. This is to ensure all rows of first table exists in final results.
Note: the condition specified in ON clause could be anything, it is not required to use Primary Keys (and you don't need to always refer to Columns from both tables)! For example:
... ON T1.title = T2.title AND T1.version < T2.version ( => see this post as a sample usage: Select only rows with max value on a column)
... ON T1.y IS NULL
... ON 1 = 0 (just as sample)
Note: Left Join = Left Outer Join, Right Join = Right Outer Join.
Simplest Definitions
Inner Join: Returns matched records from both tables.
Full Outer Join: Returns matched and unmatched records from both tables with null for unmatched records from Both Tables.
Left Outer Join: Returns matched and unmatched records only from table on Left Side.
Right Outer Join: Returns matched and unmatched records only from table on Right Side.
In-Short
Matched + Left Unmatched + Right Unmatched = Full Outer Join
Matched + Left Unmatched = Left Outer Join
Matched + Right Unmatched = Right Outer Join
Matched = Inner Join
The General Idea
Please see the answer by Martin Smith for a better illustations and explanations of the different joins, including and especially differences between FULL OUTER JOIN, RIGHT OUTER JOIN and LEFT OUTER JOIN.
These two table form a basis for the representation of the JOINs below:
CROSS JOIN
SELECT *
FROM citizen
CROSS JOIN postalcode
The result will be the Cartesian products of all combinations. No JOIN condition required:
INNER JOIN
INNER JOIN is the same as simply: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
The result will be combinations that satisfies the required JOIN condition:
LEFT OUTER JOIN
LEFT OUTER JOIN is the same as LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
The result will be everything from citizen even if there are no matches in postalcode. Again a JOIN condition is required:
Data for playing
All examples have been run on an Oracle 18c. They're available at dbfiddle.uk which is also where screenshots of tables came from.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
Blurry boundaries when playing with JOIN and WHERE
CROSS JOIN
CROSS JOIN resulting in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Using CROSS JOIN to get the result of a LEFT OUTER JOIN requires tricks like adding in a NULL row. It's omitted.
INNER JOIN
INNER JOIN becomes a cartesian products. It's the same as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
This is where the inner join can really be seen as the cross join with results not matching the condition removed. Here none of the resulting rows are removed.
Using INNER JOIN to get the result of a LEFT OUTER JOIN also requires tricks. It's omitted.
LEFT OUTER JOIN
LEFT JOIN results in rows as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN results in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
The troubles with the Venn diagram
An image internet search on "sql join cross inner outer" will show a multitude of Venn diagrams. I used to have a printed copy of one on my desk. But there are issues with the representation.
Venn diagram are excellent for set theory, where an element can be in one or both sets. But for databases, an element in one "set" seem, to me, to be a row in a table, and therefore not also present in any other tables. There is no such thing as one row present in multiple tables. A row is unique to the table.
Self joins are a corner case where each element is in fact the same in both sets. But it's still not free of any of the issues below.
The set A represents the set on the left (the citizen table) and the set B is the set on the right (the postalcode table) in below discussion.
CROSS JOIN
Every element in both sets are matched with every element in the other set, meaning we need A amount of every B elements and B amount of every A elements to properly represent this Cartesian product. Set theory isn't made for multiple identical elements in a set, so I find Venn diagrams to properly represent it impractical/impossible. It doesn't seem that UNION fits at all.
The rows are distinct. The UNION is 7 rows in total. But they're incompatible for a common SQL results set. And this is not how a CROSS JOIN works at all:
Trying to represent it like this:
..but now it just looks like an INTERSECTION, which it's certainly not. Furthermore there's no element in the INTERSECTION that is actually in any of the two distinct sets. However, it looks very much like the searchable results similar to this:
For reference one searchable result for CROSS JOINs can be seen at Tutorialgateway. The INTERSECTION, just like this one, is empty.
INNER JOIN
The value of an element depends on the JOIN condition. It's possible to represent this under the condition that every row becomes unique to that condition. Meaning id=x is only true for one row. Once a row in table A (citizen) matches multiple rows in table B (postalcode) under the JOIN condition, the result has the same problems as the CROSS JOIN: The row needs to be represented multiple times, and the set theory isn't really made for that. Under the condition of uniqueness, the diagram could work though, but keep in mind that the JOIN condition determines the placement of an element in the diagram. Looking only at the values of the JOIN condition with the rest of the row just along for the ride:
This representation falls completely apart when using an INNER JOIN with a ON 1 = 1 condition making it into a CROSS JOIN.
With a self-JOIN, the rows are in fact idential elements in both tables, but representing the tables as both A and B isn't very suitable. For example a common self-JOIN condition that makes an element in A to be matching a different element in B is ON A.parent = B.child, making the match from A to B on seperate elements. From the examples that would be a SQL like this:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Meaning Smith is the leader of both Green and Jensen.
OUTER JOIN
Again the troubles begin when one row has multiple matches to rows in the other table. This is further complicated because the OUTER JOIN can be though of as to match the empty set. But in set theory the union of any set C and an empty set, is always just C. The empty set adds nothing. The representation of this LEFT OUTER JOIN is usually just showing all of A to illustrate that rows in A are selected regardless of whether there is a match or not from B. The "matching elements" however has the same problems as the illustration above. They depend on the condition. And the empty set seems to have wandered over to A:
WHERE clause - making sense
Finding all rows from a CROSS JOIN with Smith and postalcode on the Moon:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Now the Venn diagram isn't used to reflect the JOIN. It's used only for the WHERE clause:
..and that makes sense.
When INTERSECT and UNION makes sense
INTERSECT
As explained an INNER JOIN is not really an INTERSECT. However INTERSECTs can be used on results of seperate queries. Here a Venn diagram makes sense, because the elements from the seperate queries are in fact rows that either belonging to just one of the results or both. Intersect will obviously only return results where the row is present in both queries. This SQL will result in the same row as the one above WHERE, and the Venn diagram will also be the same:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
UNION
An OUTER JOIN is not a UNION. However UNION work under the same conditions as INTERSECT, resulting in a return of all results combining both SELECTs:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
which is equivalent to:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..and gives the result:
Also here a Venn diagram makes sense:
When it doesn't apply
An important note is that these only work when the structure of the results from the two SELECT's are the same, enabling a comparison or union. The results of these two will not enable that:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
..trying to combine the results with UNION gives a
ORA-01790: expression must have same datatype as corresponding expression
For further interest read Say NO to Venn Diagrams When Explaining JOINs and sql joins as venn diagram. Both also cover EXCEPT.
In Simple Terms,
1.INNER JOIN OR EQUI JOIN : Returns the resultset that matches only the condition in both the tables.
2.OUTER JOIN : Returns the resultset of all the values from both the tables even if there is condition match or not.
3.LEFT JOIN : Returns the resultset of all the values from left table and only rows that match the condition in right table.
4.RIGHT JOIN : Returns the resultset of all the values from right table and only rows that match the condition in left table.
5.FULL JOIN : Full Join and Full outer Join are same.
left join on returns inner join on rows union all unmatched left table rows extended by nulls.
right join on returns inner join on rows union all unmatched right table rows extended by nulls.
full join on returns inner join on rowsunion all unmatched left table rows extended by nulls union all unmatched right table rows extended by nulls.
outer is optional & has no effect.
(SQL Standard 2006 SQL/Foundation 7.7 Syntax Rules 1, General Rules 1 b, 3 c & d, 5 b.)
So don't outer join on until you know what underlying inner join on is involved.
Find out what rows inner join on returns:
CROSS JOIN vs INNER JOIN in SQL
That also explains why Venn(-like) diagrams are not helpful for inner vs outer join.
For more on why they are not helpful for joins generally:
Venn Diagram for Natural Join
1.Inner Join: Also called as Join. It returns the rows present in both the Left table, and right table only if there is a match. Otherwise, it returns zero records.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2.Full Outer Join: Also called as Full Join. It returns all the rows present in both the Left table, and right table.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3.Left Outer join: Or simply called as Left Join. It returns all the rows present in the Left table and matching rows from the right table (if any).
4.Right Outer Join: Also called as Right Join. It returns matching rows from the left table (if any), and all the rows present in the Right table.
Advantages of Joins
Executes faster.
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.
Left outer join - A left outer join will give all rows in A, plus any common rows in B.
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 versay
Joins are more easily explained with an example:
To simulate persons and emails stored in separate tables,
Table A and Table B are joined by Table_A.id = Table_B.name_id
Inner Join
Only matched ids' rows are shown.
Outer Joins
Matched ids and not matched rows for Table A are shown.
Matched ids and not matched rows for Table B are shown.
Matched ids and not matched rows from both Tables are shown.
Note: Full outer join is not available on MySQL
Consider below 2 tables:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Department
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Inner Join:
Mostly written as just JOIN in sql queries. It returns only the matching records between the tables.
Find out all employees and their department names:
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
As you see above, Jose is not printed from EMP in the output as it's dept_id 6 does not find a match in the Department table. Similarly, HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table.
So, INNER JOIN or just JOIN, returns only matching rows.
LEFT JOIN :
This returns all records from the LEFT table and only matching records from the RIGHT table.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
So, if you observe the above output, all records from the LEFT table(Emp) are printed with just matching records from RIGHT table.
HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table on dept_id.
So, LEFT JOIN returns ALL rows from Left table and only matching rows from RIGHT table.
Can also check DEMO here.
There are a lot of good answers here with very accurate relational algebra examples. Here is a very simplified answer that might be helpful for amateur or novice coders with SQL coding dilemmas.
Basically, more often than not, JOIN queries boil down to two cases:
For a SELECT of a subset of A data:
use INNER JOIN when the related B data you are looking for MUST exist per database design;
use LEFT JOIN when the related B data you are looking for MIGHT or MIGHT NOT exist per database design.
The difference between inner join and outer join is as follow:
Inner join is a join that combined tables based on matching tuples, whereas outer join is a join that combined table based on both matched and unmatched tuple.
Inner join merges matched row from two table in where unmatched row are omitted, whereas outer join merges rows from two tables and unmatched rows fill with null value.
Inner join is like an intersection operation, whereas outer join is like an union operation.
Inner join is two types, whereas outer join are three types.
outer join is faster than inner join.
A Demonstration
Setup
Hop into psql and create a tiny database of cats and humans.
You can just copy-paste this whole section.
CREATE DATABASE catdb;
\c catdb;
\pset null '[NULL]' -- how to display null values
CREATE TABLE humans (
name text primary key
);
CREATE TABLE cats (
human_name text references humans(name),
name text
);
INSERT INTO humans (name)
VALUES ('Abe'), ('Ann'), ('Ben'), ('Jen');
INSERT INTO cats (human_name, name)
VALUES
('Abe', 'Axel'),
(NULL, 'Bitty'),
('Jen', 'Jellybean'),
('Jen', 'Juniper');
Querying
Here's a query we'll run several times, changing [SOMETHING JOIN] to the various types to see the results.
SELECT
humans.name AS human_name,
cats.name AS cat_name
FROM humans
[SOMETHING JOIN] cats ON humans.name = cats.human_name
ORDER BY humans.name;
An INNER JOIN returns all human-cat pairs.
Any human without a cat or cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
A FULL OUTER JOIN returns all humans and all cats, with NULL if there is no match on either side.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
A LEFT OUTER JOIN returns all humans (the left table).
Any human without a cat gets a NULL in the cat_name column.
Any cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
A RIGHT OUTER JOIN returns all cats (the right table).
Any cat without a human gets a NULL in the human_name column.
Any human without a cat is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
INNER vs OUTER
You can see that while an INNER JOIN gets only matching pairs, each kind of OUTER join includes some items without a match.
However, the actual words INNER and OUTER do not need to appear in queries:
JOIN by itself implies INNER
LEFT JOIN, RIGHT JOIN and OUTER JOIN all imply OUTER
The "outer" and "inner" are just optional elements, you are just dealing with two (three) kinds of joins. Inner joins (or what is the default when using only "join") is a join where only the elements that match the criteria are present on both tables.
The "outer" joins are the same as the inner join plus the elements of the left or right table that didn't match, adding nulls on all columns for the other table.
The full join is the inner plus the right and left joins.
In summary, if we have table A like this
idA
ColumnTableA
idB
1
Jonh
1
2
Sarah
1
3
Clark
2
4
Barbie
NULL
And table B like this:
idB
ColumnTableB
1
Connor
2
Kent
3
Spock
The inner join:
from tableA join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
Left outer join:
from tableA left join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
Right outer join:
from tableA right join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
NULL
NULL
3
Spock
Full outer join:
from tableA full join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
NULL
NULL
3
Spock

Redshift Left Join with filter drops Non-matching records [duplicate]

I have a multi-table join (only two shown in example) where I need to retain all rows from the base table. Obviously I use a LEFT JOIN to include all rows on the base table. Without the WHERE clause it works great – When a row doesn’t exist in the Right table the row from the Left table still shows, just with a 0 from the column in the Right table. The first two rows in the dataset are Labels from the Left table and Count of rows from the Right table, grouped by Label. All I want is a count of 0 when a label does not have a value from Table2 assigned.
Table1
Label | FK
----------
Blue | 1
Red | 2
Green | 3
Table2
Values | pk | Date
---------------------------
Dog | 1 | 02/02/2010
Cat | 2 | 02/02/2010
Dog | 1 | 02/02/2010
Cat | 2 | 02/02/2010
Query:
SELECT 1.Label, COUNT(2.values)
FROM Table1 1
LEFT JOIN Table2 2 ON 1.fk = 2.pk
GROUP BY 1.Label
Good Result Set - No filters
Blue | 2
Red | 2
Green | 0
Great!
My issue is that when I add filtering criteria to remove rows from the Right table the row is removed for my Left join rows (zeroing them out), the Left rows are dropped. I need the Left rows to remain even if their count is filtered down to zero.
SELECT 1.Label, COUNT(2.values)
FROM Table1 1
LEFT JOIN Table2 2 ON 1.fk = 1.pk
WHERE 2.Date BETWEEN '1/1/2010' AND '12/31/2010'
GROUP BY 1.Label
Bummer Result Set - After Filters
Blue | 2
Red | 2
Dukes!
So, what the hell? Do I need to get a temp table with the filtered dataset THEN join it to the Left table? What am I missing?
Thanks!
Do a second join or recursive join. Get my “good” join table, get a second “filtered” table, then LEFT JOIN them
You are filtering on the second table in the where. The values could be NULL and NULL fails the comparisons.
Move the where condition to the on clause:
SELECT 1.Label, COUNT(2.values)
FROM Table1 1 LEFT JOIN
Table2 2
ON 1.fk = 1.pk AND
2.Date BETWEEN 1/1/2010 AND 12/31/2010
GROUP BY 1.Label
Note:
The date formats retain the dates from the question. However, I don't advocate using BETWEEN for dates and the conditions should use standard date formats:
SELECT 1.Label, COUNT(2.values)
FROM Table1 1 LEFT JOIN
Table2 2
ON 1.fk = 1.pk AND
2.Date >= '2010-01-01' AND
2.Date < '2011-01-01'
GROUP BY 1.Label;
Some databases support the SQL Standard keyword DATE to identify date constants.
simply move the condition in WHERE clause to the ON clause.
LEFT JOIN Table2 2 ON 1.fk = 1.pk AND 2.Date BETWEEN '1/1/2010' AND '12/31/2010'
First of all i don't think it is a good idea to have number as an alias. Use a character or a word instead.
I would put the criteria in the join.
SELECT T1.Label, COUNT(T2.values)
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.fk = T1.pk
AND T2.Date BETWEEN '20100101' AND '20101231'
GROUP BY T1.Label
Other comments:
I would use ANSI(yyyyMMdd) format for the dates, so there is no missunderstanding.
I would be aware of the BETWEEN as it is not clear what you want to do if the date is '20101231 01:00' Would you like to include that date or not? >= and <= or >= and < is clearer.
If you are using SQL Server, put single quotes around the dates. If not, then it will evaluate the expression instead of the date.
BETWEEN '1/1/2010' AND '12/31/2010'

Outer Join Based On Concatenated SELECT

SO perhaps the data framework is flawed from the start, but.. I need to do an out join on two tables, but I need to do it based a concatenation of 2 column sin the second table.
For instance, table one
title | key
-------+-------
foo | Bar1
table two
subcat | pt1 | pt2
--------+-----+-----
kitty | Bar | 1
I basically need to use pt1+pt2 combined as the foreign key.
This is largely academic as I can add a column to the dataset (not my original creation) that is the concatenation, however, I wanted to know if the was possible.
Postgres version 8.4.8
cheers.bo
A join condition can be pretty much any expression; in particular, you can include string concatenation:
select ...
from t1 left outer join t2 on t1.key = t2.pt1 || t2.pt2
where ...
You can always create a sub query and perform the join against the sub query:
SELECT t1.foo, t1.key, t3.subcat FROM table1
JOIN (SELECT t2.pt1 || t2.pt2 AS ptjoined, t2.subcat
FROM tabletwo AS t2) as t3
ON t3.ptjoined = t1.key

What is the difference between "INNER JOIN" and "OUTER JOIN"?

Also, how do LEFT OUTER JOIN, RIGHT OUTER JOIN, and FULL OUTER JOIN fit in?
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
The Venn diagrams don't really do it for me.
They don't show any distinction between a cross join and an inner join, for example, or more generally show any distinction between different types of join predicate or provide a framework for reasoning about how they will operate.
There is no substitute for understanding the logical processing and it is relatively straightforward to grasp anyway.
Imagine a cross join.
Evaluate the on clause against all rows from step 1 keeping those where the predicate evaluates to true
(For outer joins only) add back in any outer rows that were lost in step 2.
(NB: In practice the query optimiser may find more efficient ways of executing the query than the purely logical description above but the final result must be the same)
I'll start off with an animated version of a full outer join. Further explanation follows.
Explanation
Source Tables
First start with a CROSS JOIN (AKA Cartesian Product). This does not have an ON clause and simply returns every combination of rows from the two tables.
SELECT A.Colour, B.Colour FROM A CROSS JOIN B
Inner and Outer joins have an "ON" clause predicate.
Inner Join. Evaluate the condition in the "ON" clause for all rows in the cross join result. If true return the joined row. Otherwise discard it.
Left Outer Join. Same as inner join then for any rows in the left table that did not match anything output these with NULL values for the right table columns.
Right Outer Join. Same as inner join then for any rows in the right table that did not match anything output these with NULL values for the left table columns.
Full Outer Join. Same as inner join then preserve left non matched rows as in left outer join and right non matching rows as per right outer join.
Some examples
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour = B.Colour
The above is the classic equi join.
Animated Version
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN ('Green','Blue')
The inner join condition need not necessarily be an equality condition and it need not reference columns from both (or even either) of the tables. Evaluating A.Colour NOT IN ('Green','Blue') on each row of the cross join returns.
SELECT A.Colour, B.Colour FROM A INNER JOIN B ON 1 =1
The join condition evaluates to true for all rows in the cross join result so this is just the same as a cross join. I won't repeat the picture of the 16 rows again.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour
Outer Joins are logically evaluated in the same way as inner joins except that if a row from the left table (for a left join) does not join with any rows from the right hand table at all it is preserved in the result with NULL values for the right hand columns.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL
This simply restricts the previous result to only return the rows where B.Colour IS NULL. In this particular case these will be the rows that were preserved as they had no match in the right hand table and the query returns the single red row not matched in table B. This is known as an anti semi join.
It is important to select a column for the IS NULL test that is either not nullable or for which the join condition ensures that any NULL values will be excluded in order for this pattern to work correctly and avoid just bringing back rows which happen to have a NULL value for that column in addition to the un matched rows.
SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour
Right outer joins act similarly to left outer joins except they preserve non matching rows from the right table and null extend the left hand columns.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON A.Colour = B.Colour
Full outer joins combine the behaviour of left and right joins and preserve the non matching rows from both the left and the right tables.
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON 1 = 0
No rows in the cross join match the 1=0 predicate. All rows from both sides are preserved using normal outer join rules with NULL in the columns from the table on the other side.
SELECT COALESCE(A.Colour, B.Colour) AS Colour FROM A FULL OUTER JOIN B ON 1 = 0
With a minor amend to the preceding query one could simulate a UNION ALL of the two tables.
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour = 'Green'
Note that the WHERE clause (if present) logically runs after the join. One common error is to perform a left outer join and then include a WHERE clause with a condition on the right table that ends up excluding the non matching rows. The above ends up performing the outer join...
... And then the "Where" clause runs. NULL= 'Green' does not evaluate to true so the row preserved by the outer join ends up discarded (along with the blue one) effectively converting the join back to an inner one.
If the intention was to include only rows from B where Colour is Green and all rows from A regardless the correct syntax would be
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour AND B.Colour = 'Green'
SQL Fiddle
See these examples run live at SQLFiddle.com.
Joins are used to combine the data from two tables, with the result being a new, temporary table. Joins are performed based on something called a predicate, which specifies the condition to use in order to perform a join. The difference between an inner join and an outer join is that an inner join will return only the rows that actually match based on the join predicate.
For eg- Lets consider Employee and Location table:
Employee
EmpID
EmpName
13
Jason
8
Alex
3
Ram
17
Babu
25
Johnson
Location
EmpID
EmpLoc
13
San Jose
8
Los Angeles
3
Pune, India
17
Chennai, India
39
Bangalore, India
Inner Join:-
Inner join creates a new result table by combining column values of two tables (Employee and Location) based upon the join-predicate. The query compares each row of Employee with each row of Location to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied by matching non-NULL values, column values for each matched pair of rows of Employee and Location are combined into a result row.
Here’s what the SQL for an inner join will look like:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Now, here is what the result of running that SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
Outer Join:-
An outer join does not require each record in the two joined tables to have a matching record. The joined table retains each record—even if no other matching record exists. Outer joins subdivide further into left outer joins and right outer joins, depending on which table's rows are retained (left or right).
Left Outer Join:-
The result of a left outer join (or simply left join) for tables Employee and Location always contains all records of the "left" table (Employee), even if the join-condition does not find any matching record in the "right" table (Location).
Here is what the SQL for a left outer join would look like, using the tables above:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Now, here is what the result of running this SQL would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
Note how while Johnson has no entry in the employee location table, he is still included in the results but the location fields are nulled.
Right Outer Join:-
A right outer join (or right join) closely resembles a left outer join, except with the treatment of the tables reversed. Every row from the "right" table (Location) will appear in the joined table at least once. If no matching row from the "left" table (Employee) exists, NULL will appear in columns from Employee for those records that have no match in Location.
This is what the SQL looks like:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Using the tables above, we can show what the result set of a right outer join would look like:
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
NULL
NULL
39
Bangalore, India
Note how while there are no employees listed as working in Bangalore, it is still included in the results with the employee fields nulled out.
Full Outer Joins:-
Full Outer Join or Full Join is to retain the nonmatching information by including nonmatching rows in the results of a join, use a full outer join. It includes all rows from both tables, regardless of whether or not the other table has a matching value.
Employee.EmpId
Employee.EmpName
Location.EmpId
Location.EmpLoc
13
Jason
13
San Jose
8
Alex
8
Los Angeles
3
Ram
3
Pune, India
17
Babu
17
Chennai, India
25
Johnson
NULL
NULL
NULL
NULL
39
Bangalore, India
MySQL 8.0 Reference Manual - Join Syntax
Oracle Join operations
Inner Join
Retrieve the matched rows only, that is, A intersect B.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Left Outer Join
Select all records from the first table, and any records in the second
table that match the joined keys.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Full Outer Join
Select all records from the second table, and any records in the first
table that match the joined keys.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
References
Inner and outer joins SQL examples and the Join block
SQL: JOINS
In simple words:
An inner join retrieve the matched rows only.
Whereas an outer join retrieve the matched rows from one table and all rows in other table ....the result depends on which one you are using:
Left: Matched rows in the right table and all rows in the left table
Right: Matched rows in the left table and all rows in the right table or
Full: All rows in all tables. It doesn't matter if there is a match or not
A inner join only shows rows if there is a matching record on the other (right) side of the join.
A (left) outer join shows rows for each record on the left hand side, even if there are no matching rows on the other (right) side of the join. If there is no matching row, the columns for the other (right) side would show NULLs.
Inner joins require that a record with a related ID exist in the joined table.
Outer joins will return records for the left side even if nothing exists for the right side.
For instance, you have an Orders and an OrderDetails table. They are related by an "OrderID".
Orders
OrderID
CustomerName
OrderDetails
OrderDetailID
OrderID
ProductName
Qty
Price
The request
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
will only return Orders that also have something in the OrderDetails table.
If you change it to OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
then it will return records from the Orders table even if they have no OrderDetails records.
You can use this to find Orders that do not have any OrderDetails indicating a possible orphaned order by adding a where clause like WHERE OrderDetails.OrderID IS NULL.
In simple words :
Inner join -> Take ONLY common records from parent and child tables WHERE primary key of Parent table matches Foreign key in Child table.
Left join ->
pseudo code
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Right join : Exactly opposite of left join . Put name of table in LEFT JOIN at right side in Right join , you get same output as LEFT JOIN.
Outer join : Show all records in Both tables No matter what. If records in Left table are not matching to right table based on Primary , Forieign key , use NULL value as result of join .
Example :
Lets assume now for 2 tables
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Here , employees table is Master table , phone_numbers_employees is child table(it contains emp_id as foreign key which connects employee.id so its child table.)
Inner joins
Take the records of 2 tables ONLY IF Primary key of employees table(its id) matches Foreign key of Child table phone_numbers_employees(emp_id).
So query would be :
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Here take only matching rows on primary key = foreign key as explained above.Here non matching rows on primary key = foreign key are skipped as result of join.
Left joins :
Left join retains all rows of the left table, regardless of whether there is a row that matches on the right table.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Outer joins :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Diagramatically it looks like :
You use INNER JOIN to return all rows from both tables where there is a match. i.e. In the resulting table all the rows and columns will have values.
In OUTER JOIN the resulting table may have empty columns. Outer join may be either LEFT or RIGHT.
LEFT OUTER JOIN returns all the rows from the first table, even if there are no matches in the second table.
RIGHT OUTER JOIN returns all the rows from the second table, even if there are no matches in the first table.
INNER JOIN requires there is at least a match in comparing the two tables. For example, table A and table B which implies A ٨ B (A intersection B).
LEFT OUTER JOIN and LEFT JOIN are the same. It gives all the records matching in both tables and all possibilities of the left table.
Similarly, RIGHT OUTER JOIN and RIGHT JOIN are the same. It gives all the records matching in both tables and all possibilities of the right table.
FULL JOIN is the combination of LEFT OUTER JOIN and RIGHT OUTER JOIN without duplication.
The answer is in the meaning of each one, so in the results.
Note :
In SQLite there is no RIGHT OUTER JOIN or FULL OUTER JOIN.
And also in MySQL there is no FULL OUTER JOIN.
My answer is based on above Note.
When you have two tables like these:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN :
You can have all of those tables data with CROSS JOIN or just with , like this:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN :
When you want to add a filter to above results based on a relation like table1.id = table2.id you can use INNER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
LEFT [OUTER] JOIN :
When you want to have all rows of one of tables in the above result -with same relation- you can use LEFT JOIN:
(For RIGHT JOIN just change place of tables)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN :
When you also want to have all rows of the other table in your results you can use FULL OUTER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Well, as your need you choose each one that covers your need ;).
Inner join.
A join is combining the rows from two tables. An inner join attempts to match up the two tables based on the criteria you specify in the query, and only returns the rows that match. If a row from the first table in the join matches two rows in the second table, then two rows will be returned in the results. If there’s a row in the first table that doesn’t match a row in the second, it’s not returned; likewise, if there’s a row in the second table that doesn’t match a row in the first, it’s not returned.
Outer Join.
A left join attempts to find match up the rows from the first table to rows in the second table. If it can’t find a match, it will return the columns from the first table and leave the columns from the second table blank (null).
INNER JOIN most typical join for two or more tables.
It returns data match on both table ON primarykey and forignkey relation.
OUTER JOIN is same as INNER JOIN, but it also include NULL data on ResultSet.
LEFT JOIN = INNER JOIN + Unmatched data of left table with Null match on right table.
RIGHT JOIN = INNER JOIN + Unmatched data of right table with Null match on left table.
FULL JOIN = INNER JOIN + Unmatched data on both right and left tables with Null matches.
Self join is not a keyword in SQL, when a table references data in itself knows as self join. Using INNER JOIN and OUTER JOIN we can write self join queries.
For example:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
I don't see much details about performance and optimizer in the other answers.
Sometimes it is good to know that only INNER JOIN is associative which means the optimizer has the most option to play with it. It can reorder the join order to make it faster keeping the same result. The optimizer can use the most join modes.
Generally it is a good practice to try to use INNER JOIN instead of the different kind of joins. (Of course if it is possible considering the expected result set.)
There are a couple of good examples and explanation here about this strange associative behavior:
Are left outer joins associative?
Does the join order matter in SQL?
Having criticized the much-loved red-shaded Venn diagram, I thought it only fair to post my own attempt.
Although #Martin Smith's answer is the best of this bunch by a long way, his only shows the key column from each table, whereas I think ideally non-key columns should also be shown.
The best I could do in the half hour allowed, I still don't think it adequately shows that the nulls are there due to absence of key values in TableB or that OUTER JOIN is actually a union rather than a join:
The precise algorithm for INNER JOIN, LEFT/RIGHT OUTER JOIN are as following:
Take each row from the first table: a
Consider all rows from second table beside it: (a, b[i])
Evaluate the ON ... clause against each pair: ON( a, b[i] ) = true/false?
When the condition evaluates to true, return that combined row (a, b[i]).
When reach end of second table without any match, and this is an Outer Join then return a (virtual) pair using Null for all columns of other table: (a, Null) for LEFT outer join or (Null, b) for RIGHT outer join. This is to ensure all rows of first table exists in final results.
Note: the condition specified in ON clause could be anything, it is not required to use Primary Keys (and you don't need to always refer to Columns from both tables)! For example:
... ON T1.title = T2.title AND T1.version < T2.version ( => see this post as a sample usage: Select only rows with max value on a column)
... ON T1.y IS NULL
... ON 1 = 0 (just as sample)
Note: Left Join = Left Outer Join, Right Join = Right Outer Join.
Simplest Definitions
Inner Join: Returns matched records from both tables.
Full Outer Join: Returns matched and unmatched records from both tables with null for unmatched records from Both Tables.
Left Outer Join: Returns matched and unmatched records only from table on Left Side.
Right Outer Join: Returns matched and unmatched records only from table on Right Side.
In-Short
Matched + Left Unmatched + Right Unmatched = Full Outer Join
Matched + Left Unmatched = Left Outer Join
Matched + Right Unmatched = Right Outer Join
Matched = Inner Join
The General Idea
Please see the answer by Martin Smith for a better illustations and explanations of the different joins, including and especially differences between FULL OUTER JOIN, RIGHT OUTER JOIN and LEFT OUTER JOIN.
These two table form a basis for the representation of the JOINs below:
CROSS JOIN
SELECT *
FROM citizen
CROSS JOIN postalcode
The result will be the Cartesian products of all combinations. No JOIN condition required:
INNER JOIN
INNER JOIN is the same as simply: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
The result will be combinations that satisfies the required JOIN condition:
LEFT OUTER JOIN
LEFT OUTER JOIN is the same as LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
The result will be everything from citizen even if there are no matches in postalcode. Again a JOIN condition is required:
Data for playing
All examples have been run on an Oracle 18c. They're available at dbfiddle.uk which is also where screenshots of tables came from.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
Blurry boundaries when playing with JOIN and WHERE
CROSS JOIN
CROSS JOIN resulting in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Using CROSS JOIN to get the result of a LEFT OUTER JOIN requires tricks like adding in a NULL row. It's omitted.
INNER JOIN
INNER JOIN becomes a cartesian products. It's the same as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
This is where the inner join can really be seen as the cross join with results not matching the condition removed. Here none of the resulting rows are removed.
Using INNER JOIN to get the result of a LEFT OUTER JOIN also requires tricks. It's omitted.
LEFT OUTER JOIN
LEFT JOIN results in rows as The General Idea/CROSS JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN results in rows as The General Idea/INNER JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
The troubles with the Venn diagram
An image internet search on "sql join cross inner outer" will show a multitude of Venn diagrams. I used to have a printed copy of one on my desk. But there are issues with the representation.
Venn diagram are excellent for set theory, where an element can be in one or both sets. But for databases, an element in one "set" seem, to me, to be a row in a table, and therefore not also present in any other tables. There is no such thing as one row present in multiple tables. A row is unique to the table.
Self joins are a corner case where each element is in fact the same in both sets. But it's still not free of any of the issues below.
The set A represents the set on the left (the citizen table) and the set B is the set on the right (the postalcode table) in below discussion.
CROSS JOIN
Every element in both sets are matched with every element in the other set, meaning we need A amount of every B elements and B amount of every A elements to properly represent this Cartesian product. Set theory isn't made for multiple identical elements in a set, so I find Venn diagrams to properly represent it impractical/impossible. It doesn't seem that UNION fits at all.
The rows are distinct. The UNION is 7 rows in total. But they're incompatible for a common SQL results set. And this is not how a CROSS JOIN works at all:
Trying to represent it like this:
..but now it just looks like an INTERSECTION, which it's certainly not. Furthermore there's no element in the INTERSECTION that is actually in any of the two distinct sets. However, it looks very much like the searchable results similar to this:
For reference one searchable result for CROSS JOINs can be seen at Tutorialgateway. The INTERSECTION, just like this one, is empty.
INNER JOIN
The value of an element depends on the JOIN condition. It's possible to represent this under the condition that every row becomes unique to that condition. Meaning id=x is only true for one row. Once a row in table A (citizen) matches multiple rows in table B (postalcode) under the JOIN condition, the result has the same problems as the CROSS JOIN: The row needs to be represented multiple times, and the set theory isn't really made for that. Under the condition of uniqueness, the diagram could work though, but keep in mind that the JOIN condition determines the placement of an element in the diagram. Looking only at the values of the JOIN condition with the rest of the row just along for the ride:
This representation falls completely apart when using an INNER JOIN with a ON 1 = 1 condition making it into a CROSS JOIN.
With a self-JOIN, the rows are in fact idential elements in both tables, but representing the tables as both A and B isn't very suitable. For example a common self-JOIN condition that makes an element in A to be matching a different element in B is ON A.parent = B.child, making the match from A to B on seperate elements. From the examples that would be a SQL like this:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Meaning Smith is the leader of both Green and Jensen.
OUTER JOIN
Again the troubles begin when one row has multiple matches to rows in the other table. This is further complicated because the OUTER JOIN can be though of as to match the empty set. But in set theory the union of any set C and an empty set, is always just C. The empty set adds nothing. The representation of this LEFT OUTER JOIN is usually just showing all of A to illustrate that rows in A are selected regardless of whether there is a match or not from B. The "matching elements" however has the same problems as the illustration above. They depend on the condition. And the empty set seems to have wandered over to A:
WHERE clause - making sense
Finding all rows from a CROSS JOIN with Smith and postalcode on the Moon:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Now the Venn diagram isn't used to reflect the JOIN. It's used only for the WHERE clause:
..and that makes sense.
When INTERSECT and UNION makes sense
INTERSECT
As explained an INNER JOIN is not really an INTERSECT. However INTERSECTs can be used on results of seperate queries. Here a Venn diagram makes sense, because the elements from the seperate queries are in fact rows that either belonging to just one of the results or both. Intersect will obviously only return results where the row is present in both queries. This SQL will result in the same row as the one above WHERE, and the Venn diagram will also be the same:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
UNION
An OUTER JOIN is not a UNION. However UNION work under the same conditions as INTERSECT, resulting in a return of all results combining both SELECTs:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
which is equivalent to:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..and gives the result:
Also here a Venn diagram makes sense:
When it doesn't apply
An important note is that these only work when the structure of the results from the two SELECT's are the same, enabling a comparison or union. The results of these two will not enable that:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
..trying to combine the results with UNION gives a
ORA-01790: expression must have same datatype as corresponding expression
For further interest read Say NO to Venn Diagrams When Explaining JOINs and sql joins as venn diagram. Both also cover EXCEPT.
In Simple Terms,
1.INNER JOIN OR EQUI JOIN : Returns the resultset that matches only the condition in both the tables.
2.OUTER JOIN : Returns the resultset of all the values from both the tables even if there is condition match or not.
3.LEFT JOIN : Returns the resultset of all the values from left table and only rows that match the condition in right table.
4.RIGHT JOIN : Returns the resultset of all the values from right table and only rows that match the condition in left table.
5.FULL JOIN : Full Join and Full outer Join are same.
left join on returns inner join on rows union all unmatched left table rows extended by nulls.
right join on returns inner join on rows union all unmatched right table rows extended by nulls.
full join on returns inner join on rowsunion all unmatched left table rows extended by nulls union all unmatched right table rows extended by nulls.
outer is optional & has no effect.
(SQL Standard 2006 SQL/Foundation 7.7 Syntax Rules 1, General Rules 1 b, 3 c & d, 5 b.)
So don't outer join on until you know what underlying inner join on is involved.
Find out what rows inner join on returns:
CROSS JOIN vs INNER JOIN in SQL
That also explains why Venn(-like) diagrams are not helpful for inner vs outer join.
For more on why they are not helpful for joins generally:
Venn Diagram for Natural Join
1.Inner Join: Also called as Join. It returns the rows present in both the Left table, and right table only if there is a match. Otherwise, it returns zero records.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2.Full Outer Join: Also called as Full Join. It returns all the rows present in both the Left table, and right table.
Example:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3.Left Outer join: Or simply called as Left Join. It returns all the rows present in the Left table and matching rows from the right table (if any).
4.Right Outer Join: Also called as Right Join. It returns matching rows from the left table (if any), and all the rows present in the Right table.
Advantages of Joins
Executes faster.
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.
Left outer join - A left outer join will give all rows in A, plus any common rows in B.
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 versay
Joins are more easily explained with an example:
To simulate persons and emails stored in separate tables,
Table A and Table B are joined by Table_A.id = Table_B.name_id
Inner Join
Only matched ids' rows are shown.
Outer Joins
Matched ids and not matched rows for Table A are shown.
Matched ids and not matched rows for Table B are shown.
Matched ids and not matched rows from both Tables are shown.
Note: Full outer join is not available on MySQL
Consider below 2 tables:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Department
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Inner Join:
Mostly written as just JOIN in sql queries. It returns only the matching records between the tables.
Find out all employees and their department names:
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
As you see above, Jose is not printed from EMP in the output as it's dept_id 6 does not find a match in the Department table. Similarly, HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table.
So, INNER JOIN or just JOIN, returns only matching rows.
LEFT JOIN :
This returns all records from the LEFT table and only matching records from the RIGHT table.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
So, if you observe the above output, all records from the LEFT table(Emp) are printed with just matching records from RIGHT table.
HR and R&D rows are not printed from Department table as they didn't find a match in the Emp table on dept_id.
So, LEFT JOIN returns ALL rows from Left table and only matching rows from RIGHT table.
Can also check DEMO here.
There are a lot of good answers here with very accurate relational algebra examples. Here is a very simplified answer that might be helpful for amateur or novice coders with SQL coding dilemmas.
Basically, more often than not, JOIN queries boil down to two cases:
For a SELECT of a subset of A data:
use INNER JOIN when the related B data you are looking for MUST exist per database design;
use LEFT JOIN when the related B data you are looking for MIGHT or MIGHT NOT exist per database design.
The difference between inner join and outer join is as follow:
Inner join is a join that combined tables based on matching tuples, whereas outer join is a join that combined table based on both matched and unmatched tuple.
Inner join merges matched row from two table in where unmatched row are omitted, whereas outer join merges rows from two tables and unmatched rows fill with null value.
Inner join is like an intersection operation, whereas outer join is like an union operation.
Inner join is two types, whereas outer join are three types.
outer join is faster than inner join.
A Demonstration
Setup
Hop into psql and create a tiny database of cats and humans.
You can just copy-paste this whole section.
CREATE DATABASE catdb;
\c catdb;
\pset null '[NULL]' -- how to display null values
CREATE TABLE humans (
name text primary key
);
CREATE TABLE cats (
human_name text references humans(name),
name text
);
INSERT INTO humans (name)
VALUES ('Abe'), ('Ann'), ('Ben'), ('Jen');
INSERT INTO cats (human_name, name)
VALUES
('Abe', 'Axel'),
(NULL, 'Bitty'),
('Jen', 'Jellybean'),
('Jen', 'Juniper');
Querying
Here's a query we'll run several times, changing [SOMETHING JOIN] to the various types to see the results.
SELECT
humans.name AS human_name,
cats.name AS cat_name
FROM humans
[SOMETHING JOIN] cats ON humans.name = cats.human_name
ORDER BY humans.name;
An INNER JOIN returns all human-cat pairs.
Any human without a cat or cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
A FULL OUTER JOIN returns all humans and all cats, with NULL if there is no match on either side.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
A LEFT OUTER JOIN returns all humans (the left table).
Any human without a cat gets a NULL in the cat_name column.
Any cat without a human is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
A RIGHT OUTER JOIN returns all cats (the right table).
Any cat without a human gets a NULL in the human_name column.
Any human without a cat is excluded.
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
INNER vs OUTER
You can see that while an INNER JOIN gets only matching pairs, each kind of OUTER join includes some items without a match.
However, the actual words INNER and OUTER do not need to appear in queries:
JOIN by itself implies INNER
LEFT JOIN, RIGHT JOIN and OUTER JOIN all imply OUTER
The "outer" and "inner" are just optional elements, you are just dealing with two (three) kinds of joins. Inner joins (or what is the default when using only "join") is a join where only the elements that match the criteria are present on both tables.
The "outer" joins are the same as the inner join plus the elements of the left or right table that didn't match, adding nulls on all columns for the other table.
The full join is the inner plus the right and left joins.
In summary, if we have table A like this
idA
ColumnTableA
idB
1
Jonh
1
2
Sarah
1
3
Clark
2
4
Barbie
NULL
And table B like this:
idB
ColumnTableB
1
Connor
2
Kent
3
Spock
The inner join:
from tableA join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
Left outer join:
from tableA left join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
Right outer join:
from tableA right join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
NULL
NULL
3
Spock
Full outer join:
from tableA full join tableB on tableA.idB = tableB.idB
idA
ColumnTableA
idB
ColumnTableB
1
Jonh
1
Connor
2
Sarah
1
Connor
3
Clark
2
Kent
4
Barbie
NULL
NULL
NULL
NULL
3
Spock