设为首页 收藏本站
查看: 1023|回复: 0

[经验分享] SQL 语句中不同的连接操作

[复制链接]

尚未签到

发表于 2018-10-21 11:54:43 | 显示全部楼层 |阅读模式
  本文摘自  www.open-open.com   详细链接为:http://www.open-open.com/solution/view/1389339225820
  SQL 语句中,表连接的方式从根本上分为五种:

  •   EQUI JOIN
  •   SEMI JOIN
  •   ANTI JOIN
  •   CROSS JOIN
  •   DIVISION
  EQUI JOIN
  这是一种最普通的 JOIN 操作,它包含两种连接方式:

  •   INNER JOIN(或者是 JOIN )
  •   OUTER JOIN(包括: LEFT 、 RIGHT、 FULL OUTER JOIN)
  用例子最容易说明其中区别:
-- This table reference contains authors and their books.  
-- There is one record for each book and its author.
  
-- authors without books are NOT included
  
author JOIN book ON author.id = book.author_id
  

  
-- This table reference contains authors and their books
  
-- There is one record for each book and its author.
  
-- ... OR there is an "empty" record for authors without books
  
-- ("empty" meaning that all book columns are NULL)
  
author LEFT OUTER JOIN book ON author.id = book.author_id
  SEMI JOIN
  这种连接关系在 SQL 中有两种表现方式:使用 IN,或者使用 EXISTS。“ SEMI ”在拉丁文中是“半”的意思。这种连接方式是只连接目标表的一部分。这是什么意思呢?再想一下上面关于作者和书名的连接。我们想象一下这样的情况:我们不需要作者 / 书名这样的组合,只是需要那些在书名表中的书的作者信息。那我们就能这么写:
-- Using IN  
FROM author
  
WHERE author.id IN (SELECT book.author_id FROM book)
  

  
-- Using EXISTS
  
FROM author
  
WHERE EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)
  尽管没有严格的规定说明你何时应该使用 IN ,何时应该使用 EXISTS ,但是这些事情你还是应该知道的:

  •   IN比 EXISTS 的可读性更好


  •   EXISTS 比IN 的表达性更好(更适合复杂的语句)


  •   二者之间性能没有差异(但对于某些数据库来说性能差异会非常大)
  因为使用 INNER JOIN 也能得到书名表中书所对应的作者信息,所以很多初学者机会认为可以通过 DISTINCT 进行去重,然后将 SEMI JOIN 语句写成这样:
-- Find only those authors who also have books  
SELECT DISTINCT first_name, last_name
  
FROM author
  
JOIN book ON author.id = book.author_id
  这是一种很糟糕的写法,原因如下:

  •   SQL 语句性能低下:因为去重操作( DISTINCT )需要数据库重复从硬盘中读取数据到内存中。(译者注: DISTINCT 的确是一种很耗费资源的操作,但是每种数据库对于 DISTINCT 的操作方式可能不同)。


  •   这么写并非完全正确:尽管也许现在这么写不会出现问题,但是随着 SQL 语句变得越来越复杂,你想要去重得到正确的结果就变得十分困难。
  更多的关于滥用 DISTINCT 的危害可以参考这篇博文
  (http://blog.jooq.org/2013/07/30/10-common-mistakes-java-developers-make-when-writing-sql/)。
  ANTI JOIN
  这种连接的关系跟 SEMI JOIN 刚好相反。在 IN 或者 EXISTS 前加一个 NOT 关键字就能使用这种连接。举个例子来说,我们列出书名表里没有书的作者:
-- Using IN  
FROM author
  
WHERE author.id NOT IN (SELECT book.author_id FROM book)
  

  
-- Using EXISTS
  
FROM author
  
WHERE NOT EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)
  关于性能、可读性、表达性等特性也完全可以参考 SEMI JOIN。
  这篇博文介绍了在使用 NOT IN 时遇到 NULL 应该怎么办,因为有一点背离本篇主题,就不详细介绍,有兴趣的同学可以读一下
  (http://blog.jooq.org/2012/01/27/sql-incompatibilities-not-in-and-null-values/)。
  CROSS JOIN
  这个连接过程就是两个连接的表的乘积:即将第一张表的每一条数据分别对应第二张表的每条数据。我们之前见过,这就是逗号在 FROM 语句中的用法。在实际的应用中,很少有地方能用到 CROSS JOIN,但是一旦用上了,你就可以用这样的 SQL语句表达:
-- Combine every author with every book  
author CROSS JOIN book
  DIVISION
  DIVISION 的确是一个怪胎。简而言之,如果 JOIN 是一个乘法运算,那么 DIVISION 就是 JOIN 的逆过程。DIVISION 的关系很难用 SQL 表达出来,介于这是一个新手指南,解释 DIVISION 已经超出了我们的目的。但是有兴趣的同学还是可以来看看这三篇文章
  (http://blog.jooq.org/2012/03/30/advanced-sql-relational-division-in-jooq/)
  (http://en.wikipedia.org/wiki/Relational_algebra#Division)
  (https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/)。
推荐阅读 →_→ 《画图解释SQL联合语句》
  我们学到了什么?
  学到了很多!让我们在脑海中再回想一下。 SQL 是对表的引用, JOIN 则是一种引用表的复杂方式。但是 SQL 语言的表达方式和实际我们所需要的逻辑关系之间是有区别的,并非所有的逻辑关系都能找到对应的 JOIN 操作,所以这就要我们在平时多积累和学习关系逻辑,这样你就能在以后编写 SQL 语句中选择适当的 JOIN 操作了。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-624457-1-1.html 上篇帖子: SVN之三:Visualsvn Server简易部署及目录权限 下篇帖子: SQL语句优化技巧
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表