A Visual Explanation of SQL Joins

I thought Ligaya Turmelle's post on SQL joins was a great primer for novice developers. Since SQL joins appear to be set-based, the use of Venn diagrams to explain them seems, at first blush, to be a natural fit. However, like the commenters to her post, I found that the Venn diagrams didn't quite match the SQL join syntax reality in my testing.

I love the concept, though, so let's see if we can make it work. Assume we have the following two tables. Table A is on the left, and Table B is on the right. We'll populate them with four records each.

id name       id  name
-- ---- -- ----
1 Pirate 1 Rutabaga
2 Monkey 2 Pirate
3 Ninja 3 Darth Vader
4 Spaghetti 4 Ninja

Let's join these tables by the name field in a few different ways and see if we can get a conceptual match to those nifty Venn diagrams.

SELECT * FROM TableA
INNER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
3 Ninja 4 Ninja

Inner join produces only the set of records that match in both Table A and Table B.

SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader

Full outer join produces the set of all records in Table A and Table B, with matching records from both sides where available. If there is no match, the missing side will contain null.

SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null

Left outer join produces a complete set of records from Table A, with the matching records (where available) in Table B. If there is no match, the right side will contain null.

SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableB.id IS null id name id name
-- ---- -- ----
2 Monkey null null
4 Spaghetti null null

To produce the set of records only in Table A, but not in Table B, we perform the same left outer join, then exclude the records we don't want from the right side via a where clause.

SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableA.id IS null
OR TableB.id IS null
id name id name
-- ---- -- ----
2 Monkey null null
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader

To produce the set of records unique to Table A and Table B, we perform the same full outer join, then exclude the records we don't want from both sides via a where clause.

There's also a cartesian product or cross join, which as far as I can tell, can't be expressed as a Venn diagram:

SELECT * FROM TableA
CROSS JOIN TableB

This joins "everything to everything", resulting in 4 x 4 = 16 rows, far more than we had in the original sets. If you do the math, you can see why this is a very dangerous join to run against large tables.

对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。Coding Horror上有一篇文章(实在不清楚为什么Coding Horror也被墙)通过 文氏图 Venn diagrams 解释了SQL的Join。我觉得清楚易懂,转过来。

假设我们有两张表。

  • Table A 是左边的表。
  • Table B 是右边的表。

其各有四条记录,其中有两条记录是相同的,如下所示:

id name       id  name
-- ---- -- ----
1 Pirate 1 Rutabaga
2 Monkey 2 Pirate
3 Ninja 3 Darth Vader
4 Spaghetti 4 Ninja

下面让我们来看看不同的Join会产生什么样的结果。

SELECT * FROM TableA
INNER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
3 Ninja 4 Ninja

Inner join
产生的结果集中,是A和B的交集。

SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader

Full outer join 产生A和B的并集。但是需要注意的是,对于没有匹配的记录,则会以null做为值。

SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null

Left outer join 产生表A的完全集,而B表中匹配的则有值,没有匹配的则以null值取代。

SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableB.id IS null id name id name
-- ---- -- ----
2 Monkey null null
4 Spaghetti null null

产生在A表中有而在B表中没有的集合。

SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.name = TableB.name
WHERE TableA.id IS null
OR TableB.id IS null

id name id name
-- ---- -- ----
2 Monkey null null
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader

产生A表和B表都没有出现的数据集。

还需要注册的是我们还有一个是“交差集” cross join, 这种Join没有办法用文式图表示,因为其就是把表A和表B的数据进行一个N*M的组合,即笛卡尔积。表达式如下:

SELECT * FROM TableA
CROSS JOIN TableB

这个笛卡尔乘积会产生 4 x 4 = 16 条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。

(全文完)

sql jion的更多相关文章

  1. SQL使用总结

    本文为转载:对于SQL的学习与使用,推荐大家去这儿,讲的很系统: http://www.w3school.com.cn/sql/index.asp 练习SQL的使用,推荐大家去这里: https:// ...

  2. Left Jion等价SQL猜想验证

    猜想:以下两条SQL等价 select * from A left join B on A.ID=B.BID and B.BName=N'小明' select * from A left join ( ...

  3. SQL Server进阶(四):联接-cross join、inner join、left join、right jion、union、union all

    测试数据脚本 CREATE TABLE Atable ( S# INT, Sname ), Sage INT, Sfrom ) ) insert into Atable ,N,N'A' union a ...

  4. Oracle SQL——inner jion;left join;right join的区别和使用场景

    背景 在一次面试的时候,面试官让我说一下这三者的使用场景和区别,当时瞬间懵逼,哈哈.回来赶快看一看,记下来. 详解 inner join 等值查询:返回两张表中,联结字段值相等的组合记录 举例:所有学 ...

  5. 一个对inner jion ...on 的sql多表联合查询的练习

    create database practiceSql; use practiceSql; -- create table student( `id` bigint not null auto_inc ...

  6. SQL SERVER 中的提示

    提示是指定的强制选项或策略,由 SQL Server 查询处理器针对 SELECT.INSERT.UPDATE 或 DELETE 语句执行. 提示将覆盖查询优化器可能为查询选择的任何执行计划. 注意: ...

  7. [转]一个用户SQL慢查询分析,原因及优化

    来源:http://blog.rds.aliyun.com/2014/05/23/%E4%B8%80%E4%B8%AA%E7%94%A8%E6%88%B7sql%E6%85%A2%E6%9F%A5%E ...

  8. SQL表连接查询(inner join、full join、left join、right join)

    SQL表连接查询(inner join.full join.left join.right join) 前提条件:假设有两个表,一个是学生表,一个是学生成绩表. 表的数据有: 一.内连接-inner ...

  9. sql之多表连接

    最近遇到特别多多表连接的问题,因此随笔记下,开始学java和mysql的时间太短,有见解不周的地方,希望读者可以提出探讨. 对于left join.right join和inner join(join ...

随机推荐

  1. phonegap安卓视频播放解决方案

    使用phonegap开发的时候,视频播放很多人一开始选择用html5的Video标签作为备选方案,实际上这种方案在真实环境下常常是无法满足需求的,因为目前HTML5的Video标签只支持MP4,OGG ...

  2. hdu 2196(Computer 树形dp)

    A school bought the first computer some time ago(so this computer's id is 1). During the recent year ...

  3. [Luogu1979][NOIP2013]华容道(BFS+SPFA)

    考虑从起点到终点的过程,一定是先将空格子移到指定格子旁边,和指定格子交换,再移到下一个指定格子要到的地方,再交换,如此反复. 于是问题分为两个部分: 1.给定两个曼哈顿距离为2的格子求最短路,BFS即 ...

  4. 解决maven无法下载jar的问题

    先去本地仓库查看是否有没有jar包,如果没有并且存在除jar包以外的文件,先将文件删除,重新用maven下载一遍.如果还是不行,就自己下载jar包导入到本地仓库,但是不能手动的添加文件夹和pom.xm ...

  5. 1.3 (JavaScript学习笔记)JavaScript对象

    在JavaScript中所有事物都是对象,字符串.数值.数组.函数...等, JavaScript还允许自定义对象.这些在1.1中有所介绍. 一.遍历对象属性 <!DOCTYPE html> ...

  6. poj 1654:Area 区域 ---- 叉积(求多边形面积)

    Area   Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19398   Accepted: 5311 利用叉积求多边形面 ...

  7. php函数前面加&符号 和 变量前面加&符号的意义

    php函数前面加&符号 和 变量前面加&符号的意义 php函数前面加&符号的意思是函数的引用返回,php函数前面加&符号有什么作用呢 function &tes ...

  8. 简单实现ToolStripMenuItem(菜单栏)的单选效果

    来源:http://www.97world.com/archives/2194 这几天在写又拍云的客户端,老实说确实学到了不少东西!接下来的几天我会把一些技巧或者原来没有接触过的一些东西发上来,算是复 ...

  9. node webkit (nw.js) 无法调试的结局方案之一

    之前做过nw项目,当时主要内容是由别人做的!过后回到家中,自己研究了下这方面.结果发现我自己写的nw 客户端不可以调试!在网上各种找办法,没找到,深感绝望,突然看到 (https://github.c ...

  10. wince5.0 plat form builder下载

    学习嵌入式开发的朋友都知道,嵌入式开发主要用到2个软件一个是Platform Builder for Windows CE 5.0一个是VS.NET2005,其中VS.NET2005网上很容易下载,现 ...