浅谈T-SQL中的联接查询
引言
平时开发时,经常会使用数据库进行增删改查,免不了会涉及多表联接。今天就简单的记录下T-SQL下的联接操作。
联接类型及其介绍
在T-SQL中联接操作使用的是JOIN表运算符。联接有三种基本的类型,分别是:交叉联接、内联接和外联接。这三种联接的区别在于它们的逻辑查询处理步骤不同。每一种联接都有一套不同的步骤。
交叉连接:
只有一个步骤:笛卡尔积
内连接:
两个步骤:笛卡尔积、使用ON关键字进行过滤
外连接:
三个步骤:笛卡尔积、ON关键字过滤、添加外部行
强调的一点:
联接查询的逻辑步骤是需要比对两张表的数据的,听起来好像比较低效,但这是逻辑上的步骤。在实际的查询中RDBMS引擎去负责数据的查询,RDBMS在实际查询时会走"捷径",只要保证实际查询的结果和逻辑上获取的结果保持一致即可。所以说,我们SQL上写法是逻辑步骤的描述过程,但实际的执行引擎通过优化,会走很多的捷径来加快数据的检索。
交叉联接
交叉联接在逻辑上是最简单的一种联接操作。他只有一个步骤就是笛卡尔积。假设表A存在m行数据,表B存在n行数据,对A,B两张表进行交叉联接会得到m*n行数据。T-SQL 92的语法如下:
select E1.empid,E2.empid from HR.Employees as E1
cross join HR.Employees as E2
在HR.Employee表中我们存放有9条数据。通过对同一张表进行交叉联接,我们会得到81行数据。E2表中的每一行都会映射到E1表的全部数据行。
内联接
内联接有两个步骤:笛卡尔积和ON关键字过滤。内联接使用须在两个表名之间使用INNER JOIN关键字(INNER关键字是可选的,T-SQL使用JOIN时,默认就是使用内联接)。用于对行进行过滤的条件是在ON子句中指定的(ON也称为联接条件)。
我们来看一个例子。Employee表中保存雇员的信息。Orders表存放客户下过的订单,每一个订单都有一名雇员来处理,这时会使用empid来标记该订单是哪一位雇员来处理的。通过内联结我们可以获取所有雇员处理过的订单数据。例如:
select E.empid,E.firstname,E.lastname,O.orderid
from HR.Employees as E
inner join Sales.Orders as O
on E.empid=O.empid
我们理解上面查询的逻辑步骤可以采用以下简单的方法来描述。我们可以认为将Employees表中的每一行数据与Orders表中的所有行进行比较。如果雇员的ID(Orders表中的雇员ID)与Employees表中的这一行雇员ID相同,则匹配成功。这是理解内联结的一种简单方法。其实,我们应该从逻辑处理步骤上来进行思考。内联结的第一步是笛卡尔积。雇员表是9行数据,订单表是830行数据。笛卡尔积一共是9*830=7470行数据。然后根据ON关键字来筛选。选择其中E.empid=O.empid的行,返回830行。
注意:SQL使用的是三值谓词逻辑。与HAVING和WHERE子句类似,ON子句也是使用的三值逻辑。ON子句自会返回让谓词逻辑为TRUE的行,所有FALSE和UNKNOW的行都会被过滤掉。
外联结
外联结与相比较其他两种联结,其逻辑步骤又多了一步,添加外部行。在外联结中,需要把一个表标记为"保留表",可以在表名之间使用LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN。LEFT关键字表示左表是保留表,RIGHT关键字表示右表是保留表,FULL关键字则表示左右两张表都是保留表。外联结的第三个步骤其实就是找出保留表中按照ON条件在另一个表中找不到与之匹配的那些行,然后把它们添加到结果集中。
下面我们还是通过一个例子来了解:
表Customers存放的是客户信息,Orders表存在是订单信息。现在需要查询客户和他们的订单的信息(没下过订单的客户也需要在结果集中)。这时我们可以将Customers表作为左表。请看例子:
select C.custid,companyname,orderid
from Sales.Customers as C
left outer join Sales.Orders as O
on C.custid=O.custid
Customers表中有两个客户没有下过订单,但是他们也出现在结果集中。从逻辑上讲这两个客户由于在Orders表中匹配不到数据,应该被过滤掉了(的确,他们在ON关键字这一步的确被过滤了)。但是外联结的第三步添加外部行又将他们加入进来了。
上述查询结果如下(部分):
从外联结保留表的角度看,可以认为外联结结果中的数据包含两种。内部行和外部行。内部行是那些ON关键字可以在两表之间匹配到的行。外部行则是找不到匹配的那些行。内联结只返回内部行。而外联结返回内部行和外部行。
注意
使用外联接时经常就使用ON还是WHERE作为过滤条件而迷惑。从外联结保留表中的行角度看,ON关键字的过滤条件不是最终的。换句话说ON关键字并不能决定保留表中的部分行是否会被添加到结果集中,而只是判断是否匹配另一个表中的某些行。所有,当需要表达一个非最终的条件时(即这个条件只决定哪些行可以匹配非保留表),就在ON条件中指定。当在生成外部行以后,需要应用过滤器,并且希望过滤条件是最终的,就需要在WHERE子句中指定条件。
请看例子:
假设现在需要返回没有下过订单的客户信息(只需要返回外部行)。语句如下:
select C.custid,companyname,orderid
from Sales.Customers as C
left outer join Sales.Orders as O
on C.custid=O.custid
where orderid is null
我们看到,只是在WHERE条件中指定了最终的过滤条件即可。切记,选择非保留表中的列作为过滤条件也很重要。应该选择只在外部行才取值为NULL,而在其他行取值不为NULL的某个列。
浅谈T-SQL中的联接查询的更多相关文章
- 浅谈oracle树状结构层级查询之start with ....connect by prior、level及order by
浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...
- 浅谈oracle树状结构层级查询测试数据
浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...
- 转: 浅谈C/C++中的指针和数组(二)
转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...
- 转:浅谈C/C++中的指针和数组(一)
再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...
- 转载 浅谈C/C++中的static和extern关键字
浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...
- 浅谈关于QT中Webkit内核浏览器
关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...
- 浅谈JAVA GUI中,AWT与Swing的区别、联系及优缺点
浅谈JAVA GUI中,AWT与Swing的区别.联系及优缺点 A.区别 1.发布的时间 AWT是在JDK 1.0版本时提出的 Swing是在AWT之后提出的(JAVA 2) 2. ”重量” AWT是 ...
- 浅谈 Swift 2 中的 Objective-C 指针
浅谈 Swift 2 中的 Objective-C 指针 2015-09-07 499 文章目录 1. 在 Swift 中读 C 指针 2. 在 Swift 中创建 C 指针 3. 总结 作者:Ja ...
- 浅谈人脸识别中的loss 损失函数
浅谈人脸识别中的loss 损失函数 2019-04-17 17:57:33 liguiyuan112 阅读数 641更多 分类专栏: AI 人脸识别 版权声明:本文为博主原创文章,遵循CC 4.0 ...
随机推荐
- 6 this的使用方法
class Person { String name; void talk() { System.out.println("my name is "+this.name); } } ...
- 【caffe】未定义函数或变量caffe_
@tag: caffe windows10上配置好caffe后(配置了matlab接口),运行caffe-master/matlab/demo/classification_demo.m报错,提示: ...
- php热身2:CRUD with Ajax
这次热身是一个会员管理系统,包括会员注册.登录.资料修改功能,使用ajax技术 1.建表 use common_module; create table if not exists member( u ...
- 【bzoj2118】 墨墨的等式
http://www.lydsy.com/JudgeOnline/problem.php?id=2118 (题目链接) 题意 给出${B}$的取值范围${[Bmin,Bmax]}$,求方程${a_{1 ...
- 学习通过Thread+Handler实现非UI线程更新UI组件
[Android线程机制] 出于性能考虑,Android的UI操作并不是线程安全的,这就意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为了解决这个问题,Android制定了一条简单的规则 ...
- crawler:简要了解一下PhantomJS
有时,我们需要浏览器处理网页,但并不需要浏览,比如生成网页的截图.抓取网页数据等操作.PhantomJS的功能,就是提供一个浏览器环境的命令行接口,你可以把它看作一个“虚拟浏览器”,除了不能浏览,其他 ...
- RBM Formula Deduction
Energy based Model the probability distribution (softmax function): \[p(x)=\frac{\exp(-E(x))}{\sum\l ...
- android toast几种使用方法
toast经常会用到,今天做个总结,特别是自定义toast的布局,值得一看. 一.默认展示 // 第一个参数:当前的上下文环境.可用getApplicationContext()或this // 第二 ...
- 2015年10月份经常使用的linux命令。
ps -ef |grep 服务名 详细的介绍可以参考此篇博客http://www.cnblogs.com/wangkangluo1/archive/2011/09/23/218593 ...
- Matlab小技巧
记录一些用Matlab的技巧. //imshow全屏 subplot(1,3,3); imshow(topSketMat); hold on; set(gcf, 'units', 'normalize ...