Click here to Skip to main content
Email Password   helpLost your password?

Introduction

This is just a simple article visually explaining SQL JOINs.

Background

I'm a pretty visual person. Things seem to make more sense as a picture. I looked all over the Internet for a good graphical representation of SQL JOINs, but I couldn't find any to my liking. Some had good diagrams but lacked completeness (they didn't have all the possible JOINs), and some were just plain terrible. So, I decided to create my own and write an article about it.

Using the code

I am going to discuss seven different ways you can return data from two relational tables. I will be excluding cross Joins and self referencing Joins. The seven Joins I will discuss are shown below:

  1. INNER JOIN
  2. LEFT JOIN
  3. RIGHT JOIN
  4. OUTER JOIN
  5. LEFT JOIN EXCLUDING INNER JOIN
  6. RIGHT JOIN EXCLUDING INNER JOIN
  7. OUTER JOIN EXCLUDING INNER JOIN

For the sake of this article, I'll refer to 5, 6, and 7 as LEFT EXCLUDING JOIN, RIGHT EXCLUDING JOIN, and OUTER EXCLUDING JOIN, respectively. Some may argue that 5, 6, and 7 are not really joining the two tables, but for simplicity, I will still refer to these as Joins because you use a SQL Join in each of these queries (but exclude some records with a WHERE clause).

Inner JOIN

INNER_JOIN.png

This is the simplest, most understood Join and is the most common. This query will return all of the records in the left table (table A) that have a matching record in the right table (table B). This Join is written as follows:

SELECT <select_list> 
FROM Table_A A
INNER JOIN Table_B B
ON A.Key = B.Key

Left JOIN

LEFT_JOIN.png

This query will return all of the records in the left table (table A) regardless if any of those records have a match in the right table (table B). It will also return any matching records from the right table. This Join is written as follows:

SELECT <select_list>
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key

Right JOIN

RIGHT_JOIN.png

This query will return all of the records in the right table (table B) regardless if any of those records have a match in the left table (table A). It will also return any matching records from the left table. This Join is written as follows:

SELECT <select_list>
FROM Table_A A
RIGHT JOIN Table_B B
ON A.Key = B.Key

Outer JOIN

FULL_OUTER_JOIN.png

This Join can also be referred to as a FULL OUTER JOIN or a FULL JOIN. This query will return all of the records from both tables, joining records from the left table (table A) that match records from the right table (table B). This Join is written as follows:

SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key

Left Excluding JOIN

LEFT_EXCLUDING_JOIN.png

This query will return all of the records in the left table (table A) that do not match any records in the right table (table B). This Join is written as follows:

SELECT <select_list> 
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

Right Excluding JOIN

RIGHT_EXCLUDING_JOIN.png

This query will return all of the records in the right table (table B) that do not match any records in the left table (table A). This Join is written as follows:

SELECT <select_list>
FROM Table_A A
RIGHT JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL

Outer Excluding JOIN

OUTER_EXCLUDING_JOIN.png

This query will return all of the records in the left table (table A) and all of the records in the right table (table B) that do not match. I have yet to have a need for using this type of Join, but all of the others, I use quite frequently. This Join is written as follows:

SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL OR B.Key IS NULL

Examples

Suppose we have two tables, Table_A and Table_B. The data in these tables are shown below:

TABLE_A
  PK Value
---- ----------
   1 FOX
   2 COP
   3 TAXI
   6 WASHINGTON
   7 DELL
   5 ARIZONA
   4 LINCOLN
  10 LUCENT

TABLE_B
  PK Value
---- ----------
   1 TROT
   2 CAR
   3 CAB
   6 MONUMENT
   7 PC
   8 MICROSOFT
   9 APPLE
  11 SCOTCH

The results of the seven Joins are shown below:

-- INNER JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
       B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
INNER JOIN Table_B B
ON A.PK = B.PK

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
   1 FOX        TROT          1
   2 COP        CAR           2
   3 TAXI       CAB           3
   6 WASHINGTON MONUMENT      6
   7 DELL       PC            7

(5 row(s) affected)
-- LEFT JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
LEFT JOIN Table_B B
ON A.PK = B.PK

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
   1 FOX        TROT          1
   2 COP        CAR           2
   3 TAXI       CAB           3
   4 LINCOLN    NULL       NULL
   5 ARIZONA    NULL       NULL
   6 WASHINGTON MONUMENT      6
   7 DELL       PC            7
  10 LUCENT     NULL       NULL

(8 row(s) affected)
-- RIGHT JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
RIGHT JOIN Table_B B
ON A.PK = B.PK

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
   1 FOX        TROT          1
   2 COP        CAR           2
   3 TAXI       CAB           3
   6 WASHINGTON MONUMENT      6
   7 DELL       PC            7
NULL NULL       MICROSOFT     8
NULL NULL       APPLE         9
NULL NULL       SCOTCH       11

(8 row(s) affected)
-- OUTER JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.PK = B.PK

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
   1 FOX        TROT          1
   2 COP        CAR           2
   3 TAXI       CAB           3
   6 WASHINGTON MONUMENT      6
   7 DELL       PC            7
NULL NULL       MICROSOFT     8
NULL NULL       APPLE         9
NULL NULL       SCOTCH       11
   5 ARIZONA    NULL       NULL
   4 LINCOLN    NULL       NULL
  10 LUCENT     NULL       NULL

(11 row(s) affected)
-- LEFT EXCLUDING JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
LEFT JOIN Table_B B
ON A.PK = B.PK
WHERE B.PK IS NULL

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
   4 LINCOLN    NULL       NULL
   5 ARIZONA    NULL       NULL
  10 LUCENT     NULL       NULL
(3 row(s) affected)
-- RIGHT EXCLUDING JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
RIGHT JOIN Table_B B
ON A.PK = B.PK
WHERE A.PK IS NULL

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
NULL NULL       MICROSOFT     8
NULL NULL       APPLE         9
NULL NULL       SCOTCH       11

(3 row(s) affected)
-- OUTER EXCLUDING JOIN
SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.PK = B.PK
WHERE A.PK IS NULL
OR B.PK IS NULL

A_PK A_Value    B_Value    B_PK
---- ---------- ---------- ----
NULL NULL       MICROSOFT     8
NULL NULL       APPLE         9
NULL NULL       SCOTCH       11
   5 ARIZONA    NULL       NULL
   4 LINCOLN    NULL       NULL
  10 LUCENT     NULL       NULL

(6 row(s) affected)

Note on the OUTER JOIN that the inner joined records are returned first, followed by the right joined records, and then finally the left joined records (at least, that's how my Microsoft SQL Server did it; this, of course, is without using any ORDER BY statement).

You can visit the Wikipedia article for more info here (however, the entry is not graphical).

I've also created a cheat sheet that you can print out if needed. If you right click on the image below and select "Save Target As...", you will download the full size image.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralExcellent.
digital man
0:23 12 Mar '10  
Can't believe I've not spotted this before: clear and easy to understand. Well done.
Tychotics
"The dinosaurs became extinct because they didn't have a space program. And if we become extinct because we don't have a space program, it'll serve us right!"
Larry Niven

GeneralGreat Article!!
Khushi_G
11:14 18 Feb '10  
great article!!


Thanks. Smile
Generalgot my 5
Omar Gamil
4:37 18 Feb '10  
simple and amazing Wink
Generalhaha
dooglex
9:40 28 Jan '10  
thahah tnkx Smile


Generalgreat article
crudeCodeYogi
8:41 24 Jan '10  
great article about joins..exact point to point... Thanks!!

If you fail to plan, you plan to fail!

Books are as useful to a stupid person as a mirror is useful to a blind person. - Chanakya

GeneralExcillent
Md. Marufuzzaman
2:59 30 Dec '09  
This is simply outstanding...

Thanks
Md. Marufuzzaman

Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.

Generalhow to add new table (after join) to a datagridview
anahita22
22:15 13 Aug '09  
hi,i have problem after joining them ,for adding the new table in datagrid view
how should i do it?
thanx for your nice jobRose
GeneralRe: how to add new table (after join) to a datagridview
C.L. Moffatt
11:58 17 Aug '09  
First, you'll have to be a little more specific. I'm really not sure what it is you are trying to accomplish.
Second, a datagridview is a little beyond the scope of this article. But if you are able to explain clearer what it is you are trying to do, I'll try to help you.
GeneralLeft outer join and right outer join
udomnoke
16:20 17 Jul '09  
Where is left and right outer join case is in.
GeneralRe: Left outer join and right outer join
C.L. Moffatt
11:59 17 Aug '09  
I don't understand your question.
GeneralReally Good!
MANISH RASTOGI
22:03 25 Jun '09  
Thanks C.L. Moffatt
QuestionArticle Translation
Rodrigo Salvaterra
8:59 13 May '09  
Hi Moffat,


Great article!! Congratulations!!!

May I translate it to Portuguese and publish it on our local site:

http://www.iguru.com.br


Best regards,
Rodrigo Salvaterra
AnswerRe: Article Translation
C.L. Moffatt
9:35 13 May '09  
Rodrigo,

Absolutely. You may indeed translate this article.

Good Luck,
C.L. Moffatt
GeneralThank you, Great job
nishchal24
23:45 5 May '09  
Hi,
You have really done a great job by putting efforts on explaining SQL JOINS in a very simple, straight, to the point and effective way.
Warm regards,
Smile
GeneralImitation?
HoyaSaxa93
5:01 14 Apr '09  
very similar post found here[^]
GeneralRe: Imitation?
C.L. Moffatt
14:40 21 Apr '09  
Are you claiming that the Code Project article is an imitation of the linked article or vice versa? The dates on both articles clearly show that the Code Project article precedes the linked article.
GeneralGood work
Donsw
8:30 24 Feb '09  
I liked the article, especially the pictures, it reminds me of the Head First series which uses a lot of pictures to help show what is going on. It is very similar to Head First SQL in it is very pictorial. I also like the reference to another site for people how want to learn more. Good work.

cheers,
Donsw
My Recent Article : Optimistic Concurrency with C# using the IOC and DI Design Patterns

GeneralGreat Stuff [modified]
weaponx2007a
15:35 17 Feb '09  
The struggle is over. I've always had trouble with those joins. Who would have thought a Venn Diagram would come to help.
This will stick!!

Thanks

modified on Tuesday, February 17, 2009 9:07 PM

GeneralGreat work
maga82
7:39 17 Feb '09  
Absolutely usefulSmile Thanks a lot for thatSmile
GeneralJust one thing to perhaps alter
Mark Greenwood
13:05 12 Feb '09  
This is a great article, the only suggestion I would have is when you are explaining the EXCLUSION joins is rather than using WHERE to say, for example, exclude table B items (e.g.
where B.key is null
) make it part of the ON clause (e.g.
on (A.key = B.key) AND (B.key is NULL)
. The reason is that it is unlikely that SQL will be as simple as a single join and your are constraining the exclusion at the point of the join rather than in the WHERE which might potentially be a long way further down the code if reading in a really complicated stored proc etc.

Otherwise it's a great article and gets my 5.

Mark.
GeneralRe: Just one thing to perhaps alter
C.L. Moffatt
18:40 12 Feb '09  
You can't do that.

This (your suggestion):

SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
LEFT JOIN Table_B B
ON A.PK = B.PK
AND B.PK IS NULL

is not the same as this (join from the article):

SELECT A.PK AS A_PK, A.Value AS A_Value,
B.Value AS B_Value, B.PK AS B_PK
FROM Table_A A
LEFT JOIN Table_B B
ON A.PK = B.PK
WHERE B.PK IS NULL

Download the sample code and try it. Your suggestion basically just returns Table_A with NULL values for all of Table_B's fields. Think about it, you basically just told SQL to join Table_A with NULL and that is what you get. The condition of A.PK = B.PK "AND" B.PK IS NULL will never occur. Think of it this way, IF B.PK = NULL "AND" B.PK = A.PK, then by substitution A.PK = NULL as well.

LEFT JOIN EXCLUDING INNER JOIN
A_PK A_Value B_Value B_PK
----------- ---------- ---------- -----------
1 FOX NULL NULL
2 COP NULL NULL
3 TAXI NULL NULL
4 LINCOLN NULL NULL
5 ARIZONA NULL NULL
6 WASHINGTON NULL NULL
7 DELL NULL NULL
10 LUCENT NULL NULL

Smile
GeneralRe: Just one thing to perhaps alter
d_camillo
13:14 13 Feb '09  
thx for pointing this out.
GeneralIdeas like this...
Trollpower
23:26 11 Feb '09  
brightens up my day. Excellent work, dude.

One idea for an improvement: The cheat sheet should have the join-name over each drawing. It will be easier to identify the type of join. Reading through the statement will work, too, but its a more direct way of identifying a join, IMHO.

TP
GeneralRe: Ideas like this...
C.L. Moffatt
18:41 12 Feb '09  
Great suggestion, I'll do this when I get the chance.
GeneralGood Work done!.
Navneet Hegde
2:44 11 Feb '09  
Thanks.

Develop2Program & Program2Develop


Last Updated 4 Feb 2009 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010