Click here to Skip to main content
Click here to Skip to main content

Visual Representation of SQL Joins

By , 3 Feb 2009
 

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

  • Initial release -- 02/03/2009.
  • Version 1.0 -- 02/04/2009 -- Fixed cheat sheet and minor typos.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

C.L. Moffatt
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberoperations12 Nov '11 - 3:02 
This article is helpful and clear enough. Finally, I understood how ANSI Sql joins work Smile | :)
 
Thanks a million!
GeneralRe: My vote of 5memberC.L. Moffatt30 Nov '11 - 9:09 
Thank you!
QuestionMy vote of 5memberDrazen Pupovac31 Oct '11 - 0:34 
Really useful article. Thank you.
GeneralMy vote of 5memberA-Lexo28 Sep '11 - 23:23 
Very informative graphs.
SuggestionFew more things to addmembershantanufrom438719 Jul '11 - 21:26 
I found pretty good link to add some more stuff to this article. Check this
GeneralRe: Few more things to addmemberC.L. Moffatt20 Jul '11 - 9:21 
I don't see how your article adds to the article above.
GeneralMy vote of 5memberReiss12 Jul '11 - 10:30 
Nice use of set theory Smile | :)
GeneralMy vote of 5memberead mahmoud19 Apr '11 - 2:58 
very clear. good work
GeneralMy vote of 5memberDaveAuld17 Apr '11 - 22:39 
First time i have seen the different joins represented in this way together on one page, and it makes it so much clearer......
GeneralMy vote of 5memberdcialdella16 Feb '11 - 4:59 
Simple ! Great !
GeneralMy vote of 5memberVijay Chandra Sekhar Parepalli12 Feb '11 - 15:58 
Best and simple I have seen so far for helping understand SQL using Venn diagrams. Good one.
GeneralMy vote of 5memberWayne Clarke1 Feb '11 - 5:08 
Excellent resource to have; especially for those queries you don't use often. I would like to see this mixed with LINQ-to-SQL as well.
GeneralMy vote of 5memberSteve Maier24 Jan '11 - 9:26 
Great little summary. I hate trying to remember how they go.
Generalmy vote of 5memberYusuf8 Jan '11 - 16:45 
Excellent article. +5

GeneralJOINSmemberthinkindia10 Dec '10 - 1:55 
REALLY  VERY VERY USEFULL

GeneralMy vote of 5memberlinuxjr23 Nov '10 - 1:53 
Nice Article. Thanks for sharing your work.
GeneralThis assumes no NULL for keysmemberLenzM3 Nov '10 - 18:34 
The last three examples assume that NULL is not a valid key.
GeneralRe: This assumes no NULL for keysmemberC.L. Moffatt28 Jan '11 - 5:46 
By default, NULL is an invalid key. You can override this setting within SQL but I cannot think of a good reason why you would do this. What is the purpose of having a primary key if you are going to set it to NULL? Also in MS-SQL, you can override this feature but only one record can have the NULL primary key (because the key needs to be unique).
 
So yes, the examples assume that NULL is not being used as a key which I think is a safe and logical assumption.
GeneralMy vote of 5membersomnath _chowdhury29 Oct '10 - 0:54 
Good Explanation
GeneralMy vote of 5memberChristophe30 Sep '10 - 2:53 
the beauty of simplicity
GeneralMy vote of 5membermaster vicky29 Sep '10 - 1:20 
Nice visual explanation Smile | :)
GeneralMy vote of 5memberPranay Rana22 Jul '10 - 1:44 
awesome........simply good , gr8
GeneralMy vote of 5memberza_10041719 Jul '10 - 0:55 
Nice!
GeneralMy vote of 5memberDarkRisingForce14 Jul '10 - 20:41 
Clear, Visual easy... Thank you
GeneralExcellent.memberdigital man11 Mar '10 - 23:23 
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!!memberKhushi_G18 Feb '10 - 10:14 
great article!!
 

Thanks. Smile | :)
Generalgot my 5memberOmar Gamil18 Feb '10 - 3:37 
simple and amazing Wink | ;)
Generalgreat articlemembercrudeCodeYogi24 Jan '10 - 7:41 
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

GeneralExcillentgroupMd. Marufuzzaman30 Dec '09 - 1:59 
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.

Questionhow to add new table (after join) to a datagridviewmemberanahita2213 Aug '09 - 21:15 
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 | [Rose]
AnswerRe: how to add new table (after join) to a datagridviewmemberC.L. Moffatt17 Aug '09 - 10:58 
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 joinmemberudomnoke17 Jul '09 - 15:20 
Where is left and right outer join case is in.
GeneralRe: Left outer join and right outer joinmemberC.L. Moffatt17 Aug '09 - 10:59 
I don't understand your question.
GeneralRe: Left outer join and right outer joinmemberUnruled Boy27 Jul '11 - 1:39 
in sql server, we have:
 
SELECT <select_list>
FROM Table_A A
LEFT OUTER JOIN Table_B B
ON A.Key = B.Key
 
and
 
SELECT <select_list>
FROM Table_A A
RIGHT OUTER JOIN Table_B B
ON A.Key = B.Key
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralRe: Left outer join and right outer joinmemberC.L. Moffatt27 Jul '11 - 11:52 
In SQL Server, the "OUTER" declaration is optional. You can easily write "LEFT JOIN" or "RIGHT JOIN" and the SQL Server will perform the exact same join. Try it.
 
So "LEFT JOIN" equals "LEFT OUTER JOIN" and "RIGHT JOIN" equals "RIGHT OUTER JOIN". They are the same thing.
GeneralRe: Left outer join and right outer joinmemberUnruled Boy27 Jul '11 - 16:54 
you are right Laugh | :laugh:
 
but I just want to explain your question, because you said " I don't understand your question." basically he just want you to mention left/right outer join explicitly in the article.Rose | [Rose]
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralReally Good!memberMANISH RASTOGI25 Jun '09 - 21:03 
Thanks C.L. Moffatt
QuestionArticle TranslationmemberRodrigo Salvaterra13 May '09 - 7:59 
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 TranslationmemberC.L. Moffatt13 May '09 - 8:35 
Rodrigo,
 
Absolutely. You may indeed translate this article.
 
Good Luck,
C.L. Moffatt
GeneralThank you, Great jobmembernishchal245 May '09 - 22:45 
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 | :)
QuestionImitation?memberHoyaSaxa9314 Apr '09 - 4:01 
very similar post found here[^]
AnswerRe: Imitation?memberC.L. Moffatt21 Apr '09 - 13:40 
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 workmemberDonsw24 Feb '09 - 7:30 
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]memberweaponx2007a17 Feb '09 - 14:35 
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 workmembermaga8217 Feb '09 - 6:39 
Absolutely usefulSmile | :) Thanks a lot for thatSmile | :)
GeneralJust one thing to perhaps altermemberMark Greenwood12 Feb '09 - 12:05 
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 altermemberC.L. Moffatt12 Feb '09 - 17:40 
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 altermemberd_camillo13 Feb '09 - 12:14 
thx for pointing this out.
GeneralIdeas like this...memberTrollpower11 Feb '09 - 22:26 
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...memberC.L. Moffatt12 Feb '09 - 17:41 
Great suggestion, I'll do this when I get the chance.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 4 Feb 2009
Article Copyright 2009 by C.L. Moffatt
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid