首页 > 数据库 > 图解SQL的Join

图解SQL的Join

2011年1月11日 发表评论 阅读评论 30,775 人阅读    

对于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的交集。

Venn diagram of SQL inner join
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做为值。

Venn diagram of SQL cartesian join
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值取代。

Venn diagram of SQL left join
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表中没有的集合。

join-left-outer.png
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表都没有出现的数据集。

join-outer.png

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

SELECT * FROM TableA
CROSS JOIN TableB

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

更新:2014年3月30日

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell.cn ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
分类: 数据库 标签: , ,
好烂啊有点差凑合看看还不错很精彩 (13 人打了分,平均分: 5.00 )
Loading ... Loading ...
  1. qklxtlx
    2011年1月11日09:03 | #1

    DT一下,昨天下午刚考的数据库=。=

  2. ddd
    2011年1月11日09:15 | #2

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

  3. 2011年1月11日09:52 | #3

    图和sql很清楚 ,谢谢!

  4. 2011年1月12日16:17 | #4

    还需要注册的是我们还有一个是“交差集” cross join

    “注册”应为”注意”

  5. nothing@null.com
    2011年1月12日16:35 | #5

    楼主好高深啊,讨论的话题好伟大啊,我们都不懂啊

  6. stone
    2011年1月12日17:21 | #6

    不错, 用图形解释比文字描述好理解多了.

  7. 2011年1月13日11:13 | #7

    比我当时的老师讲的还清楚啊

  8. Sephiroth
    2011年1月15日12:02 | #8

    还可以嵌套Join,效果更佳XD

  9. 2011年1月16日09:29 | #9

    好像跟photoshop选区添减差不多。。

  10. 2011年1月24日11:30 | #10

    @pallove 通感了

  11. AA的CC
    2011年1月27日03:02 | #11

    想问下如果直接在from后面用逗号分隔表,实际是不是也是某种形式的连接的呢?

  12. 2011年4月19日21:53 | #12

    这篇文章真牛逼,拜读。

  13. Vera
    2011年6月8日12:57 | #13

    很好啊,我记得大学时候都是(+),总是记混。。

  14. 2011年7月12日13:31 | #14

    非常不错,图解的很详细!

  15. swimstyle
    2011年7月23日03:35 | #15

    最近正学SQL,这说得图文并茂,不是一般的好,通俗易懂!

  16. 2011年8月7日14:48 | #16

    复习的时候想到了coolshell的这篇文章,用百度搜竟然搜不到原帖,google一下子就搜到了。百度为什么要隐藏coolshell呢?

  17. 倾国。
    2011年10月27日12:59 | #17

    很清晰。一下就读懂了。

  18. scott
    2011年10月28日15:28 | #18

    @AA的CC 这就是inner join

  19. scott
    2011年10月28日15:33 | #19

    @Vera 我是这么记住的:如果加号在等号的右边,那就是说左边的数值比较多,右边需要加点才能和左表匹配,,所以是左外关联

  20. Tesla
    2012年3月27日09:41 | #20

    一图胜千言!

  21. 暗夜之殇
    2012年5月3日15:30 | #21

    最好是把Left和Right相关的对比的说下 这个没有说 比较遗憾。。。

  22. 小黑斯基
    2012年7月17日19:47 | #22

    怎么感觉有点胡扯

  23. oldmonst
    2012年8月22日19:12 | #23

    确实啊;怪不得偶做full outer join的时候总是感觉不大对。。。

  24. 代号极光
    2013年10月14日10:43 | #24

    非常好,5分钟学会

  25. 2014年5月26日15:20 | #25

    图解特棒,很赞

  1. 2011年1月12日13:06 | #1
  2. 2011年3月26日01:34 | #2
  3. 2011年4月3日00:33 | #3
  4. 2011年7月15日11:33 | #4
  5. 2011年7月19日10:41 | #5
  6. 2011年7月19日16:56 | #6
  7. 2011年7月20日01:24 | #7
  8. 2011年7月20日23:14 | #8
  9. 2011年7月21日11:47 | #9
  10. 2011年7月21日14:47 | #10
  11. 2011年7月22日00:36 | #11
  12. 2011年7月24日04:18 | #12
  13. 2011年7月27日12:27 | #13
  14. 2011年7月28日09:37 | #14
  15. 2011年7月31日16:12 | #15
  16. 2011年8月2日13:44 | #16
  17. 2011年8月24日17:39 | #17
  18. 2011年8月26日11:00 | #18
  19. 2011年9月1日18:00 | #19
  20. 2011年9月16日17:36 | #20
  21. 2011年9月19日11:43 | #21
  22. 2011年10月18日18:17 | #22
  23. 2011年10月20日00:48 | #23
  24. 2011年10月24日01:25 | #24
  25. 2011年11月5日09:52 | #25
  26. 2011年12月9日12:51 | #26
  27. 2011年12月29日09:10 | #27
  28. 2012年1月21日18:45 | #28
  29. 2012年2月19日19:37 | #29
  30. 2012年2月29日23:44 | #30
  31. 2012年3月14日14:13 | #31
  32. 2012年3月19日21:16 | #32
  33. 2012年3月25日17:00 | #33
  34. 2012年5月15日10:04 | #34
  35. 2012年5月15日19:07 | #35
  36. 2012年5月16日01:58 | #36
  37. 2012年5月16日14:05 | #37
  38. 2012年5月25日22:55 | #38
  39. 2012年6月2日18:24 | #39
  40. 2012年6月3日07:42 | #40
  41. 2012年6月20日09:25 | #41
  42. 2012年6月20日10:23 | #42
  43. 2012年6月20日10:51 | #43
  44. 2012年6月20日12:36 | #44
  45. 2012年6月20日18:02 | #45
  46. 2012年6月20日18:47 | #46
  47. 2012年6月21日13:54 | #47
  48. 2012年6月22日05:41 | #48
  49. 2012年6月23日03:57 | #49
  50. 2012年6月25日11:45 | #50
  51. 2012年6月27日21:24 | #51
  52. 2012年7月3日00:03 | #52
  53. 2012年7月9日10:47 | #53
  54. 2012年7月12日15:23 | #54
  55. 2012年7月30日00:15 | #55
  56. 2012年7月31日17:07 | #56
  57. 2012年8月8日16:02 | #57
  58. 2012年8月10日11:33 | #58
  59. 2012年8月14日10:58 | #59
  60. 2012年8月18日10:52 | #60
  61. 2012年8月19日20:30 | #61
  62. 2012年8月30日13:19 | #62
  63. 2012年9月5日21:27 | #63
  64. 2012年9月25日23:05 | #64
  65. 2012年9月28日17:11 | #65
  66. 2012年10月14日13:38 | #66
  67. 2012年10月19日21:42 | #67
  68. 2012年10月21日18:10 | #68
  69. 2012年10月24日21:28 | #69
  70. 2012年10月30日20:49 | #70
  71. 2012年11月12日18:09 | #71
  72. 2012年12月13日09:51 | #72
  73. 2012年12月31日22:29 | #73
  74. 2012年12月31日23:30 | #74
  75. 2013年1月6日09:27 | #75
  76. 2013年1月15日14:42 | #76
  77. 2013年1月31日12:06 | #77
  78. 2013年2月11日23:37 | #78
  79. 2013年2月27日18:02 | #79
  80. 2013年3月8日18:14 | #80
  81. 2013年3月29日08:37 | #81
  82. 2013年4月3日01:09 | #82
  83. 2013年4月4日13:17 | #83
  84. 2013年4月5日09:35 | #84
  85. 2013年4月6日11:30 | #85
  86. 2013年4月18日22:57 | #86
  87. 2013年5月3日14:22 | #87
  88. 2013年6月7日20:13 | #88
  89. 2013年6月12日14:47 | #89
  90. 2013年6月12日17:33 | #90
  91. 2013年7月22日02:01 | #91
  92. 2013年7月22日14:29 | #92
  93. 2013年7月24日15:49 | #93
  94. 2013年7月25日08:57 | #94
  95. 2013年7月25日10:24 | #95
  96. 2013年7月27日17:38 | #96
  97. 2013年8月1日22:56 | #97
  98. 2013年8月5日16:21 | #98
  99. 2013年8月11日15:00 | #99
  100. 2013年8月24日19:56 | #100
  101. 2013年11月2日17:18 | #101
  102. 2013年11月10日16:20 | #102
  103. 2013年11月10日16:30 | #103
  104. 2013年11月10日23:25 | #104
  105. 2013年12月2日11:32 | #105
  106. 2013年12月5日03:44 | #106
  107. 2013年12月31日14:39 | #107
  108. 2014年1月15日22:28 | #108
  109. 2014年1月19日13:26 | #109
  110. 2014年2月4日23:26 | #110
  111. 2014年2月14日10:22 | #111
  112. 2014年2月28日09:42 | #112
  113. 2014年3月8日00:19 | #113
  114. 2014年3月8日16:55 | #114
  115. 2014年3月8日22:30 | #115
  116. 2014年4月1日11:43 | #116
  117. 2014年4月19日21:45 | #117
  118. 2014年5月6日23:10 | #118
  119. 2014年5月12日18:26 | #119
  120. 2014年6月13日15:56 | #120
  121. 2014年6月15日22:34 | #121
  122. 2014年8月5日14:52 | #122
  123. 2014年8月20日10:04 | #123