SQL Server【三】连接查询
将两个表或者两个以上的表以一定的连接条件连接起来,从中检索出满足条件的数据。
内连接
使用inner join
,inner
可以省略
-- 查询员工的姓名和部门名称
select "E".ename as "员工姓名", "D".dname as "部门名称"from emp "E"join dept "D"on "E".deptno = "D".deptno
select … from A, B
假设A表有xxx行,则行可以表示为集合(a1,a2,...,ax)(a_1,a_2,...,a_x)(a1,a2,...,ax)
假设B表有yyy行,则行可以表示为集合(b1,b2,...,by)(b_1,b_2,...,b_y)(b1,b2,...,by)
则select ... from A,B
就是将两个表的行进行笛卡尔成绩,并将两个行进行合并得到(a1+b1,a1+b2,...,a2+b1,a2+b2,...)(a_1+b_1,a_1+b_2,...,a_2+b_1,a_2+b_2,...)(a1+b1,a1+b2,...,a2+b1,a2+b2,...),因此总共的行数是x∗yx*yx∗y,总共的列数是两个表列数相加
即把A表的每一条记录都和B表的每一条记录组合在一起
select … from A,B where …
对上面的表用where
的条件进行过滤
select E.ename as "员工姓名", D.dname as "部门名称"from emp as "E", dept as "D"where E.deptno = D.deptno
select … from A join B on …
join
是连接的意思 on
表示连接条件
如果使用join
就必须使用on
select * from empjoin depton 1=1 --70*11select emp.ename as '员工姓名', dept.deptno as '部门编号'from empjoin depton 1 = 1 --70*2select emp.ename as '员工姓名', dept.deptno as '部门编号'from empjoin depton emp.deptno=dept.deptno --14*2select E.ename as '员工姓名', D.deptno as '部门编号'from emp as "E"join dept as "D"on E.deptno=D.deptno --14*2
select *from emp as "E"join dept as "D"on 1 =1 select *from dept as "D"join emp as "E"on 1 =1 order by D.deptnoselect * from dept,emp
where dept.deptno = emp.deptno
--实际中发现无论将哪个表放在前面,总是用行数少的表匹配行数多的
from
和join
后面可以使用别名,如果在这里使用别名,其他的地方也都必须使用别名。区别于select
后面的别名不能在其他地方使用,我认为根本原因在于语句的执行顺序
实际上和select ... from A,B where ...
等价,推荐使用join on
使用join on
可以再使用where
对得到的数据过滤,从而实现不同的分工
混合使用
select * from emp as "E", dept as "D"
where E.deptno=D.deptno and E.sal>2000
--等价于下面的写法,下面的写法更加清晰
select * from emp as "E"join dept as "D"on E.deptno = D.deptnowhere E.sal > 2000--求出工资大于2000的员工的姓名 部门编号 薪水 薪水等级
select emp.ename as "员工姓名", dept.dname as "部门名称", emp.sal as "薪水", SALGRADE.GRADE as "薪水等级"from emp,dept,SALGRADEwhere emp.deptno=dept.deptno and emp.sal>2000 and emp.sal >= SALGRADE.LOSAL and emp.sal <=SALGRADE.HISALselect emp.ename as "员工姓名", dept.dname as "部门名称", emp.sal as "薪水", SALGRADE.GRADE as "薪水等级"from empjoin depton emp.deptno=dept.deptnojoin SALGRADEon emp.sal>=SALGRADE.LOSAL and emp.sal<=SALGRADE.HISALwhere emp.sal>2000
我们也可以把查询的表当作一个表,进行子查询
-- 输出部门名称,该部门所有员工的平均工资 平均工资等级select dept.dname as "部门名称", tmp.avg_sal as "平均工资", SALGRADE.GRADE as "平均工资等级"from(select emp.deptno as "dept_no", AVG(emp.sal) as "avg_sal"from empgroup by emp.deptno) "tmp"join depton dept.deptno = tmp.dept_nojoin SALGRADEon tmp.avg_sal between SALGRADE.LOSAL and SALGRADE.HISAL
语句顺序
SELECT ...INTOFROMJOINONWHEREGROUP BYHAVINGORDER BY
-- 输出3个姓名中不含有O的工资最高的员工的姓名、工资、工资等级、部门名称select top 3 emp.ename as "员工姓名", emp.sal as "员工工资", SALGRADE.GRADE as "工资等级", dept.dname as "部门名称"from empjoin depton emp.deptno=dept.deptnojoin SALGRADEon emp.sal >= SALGRADE.LOSAL and emp.sal <= SALGRADE.HISALwhere emp.ename not like '%O%'order by emp.sal desc
当null
和not in
在一起的时候需要注意。如果表中有null
,则使用not in
的时候返回的总为空。
这与SQL的比较机制有关。在SQL中比较结果分为true``false``null
,只有结果为true
的时候系统才认为匹配成功并返回记录,in
的本质是等于的or
,not in
的本质是不等于的and
。
比较结果 | and null | or null |
---|---|---|
true | null | true |
false | false | null |
null | null | null |
当使用in
的时候因为是or
进行连接,所以可以正常返回true
,在not in
的时候是and
连接,因此返回总为null
,因此返回为空。
详细原因可以看这篇文章:传送门。为了解决这个问题我们可以使用is [not] null
和isnull()
函数组合判断
--求出emp表中所有领导的姓名select distinct E1.ename as "领导姓名"from emp "E1"join emp "E2"on E1.EMPNO = E2.mgrselect emp.ename as "领导姓名"from empwhere emp.EMPNO in (select distinct mgr from emp)--输出所有非领导的信息select *from empwhere emp.EMPNO not in (select distinct mgr from emp where mgr is not null)
--求出平均薪水最高的部门的名称和部门平均工资select dept.dname as "部门名称", tmp.avg_sal as "平均工资"from (select top 1 emp.deptno as "dept_no", AVG(emp.sal) as avg_salfrom empgroup by emp.deptnoorder by AVG(emp.sal) desc) "tmp"join depton tmp.dept_no=dept.deptno
当子查询的值只有一个的时候可以将子查询放在表达式中
--工资大于 所有员工中工资最低的人中的工资 的人中
--前三个人的姓名 工资 部门编号 部门名称 工资等级
select top 3 emp.ename as "姓名", emp.sal as "工资", emp.deptno as "部门编号", dept.dname as "部门名称", SALGRADE.GRADE as "工资等级"from empjoin (select MIN(sal) as "min_sal" from emp) as "tmp"on emp.sal > tmp.min_saljoin dept on emp.deptno = dept.deptnojoin SALGRADEon emp.sal between SALGRADE.LOSAL and SALGRADE.HISALorder by emp.sal select top 3 tmp.ename as "姓名", tmp.sal as "工资", tmp.deptno as "部门编号", dept.dname as "部门名称", SALGRADE.GRADE as "工资等级"from ( select ename,sal,deptno from emp where sal > (select MIN(sal) as "min_sal" from emp)) as "tmp"join dept on tmp.deptno = dept.deptnojoin SALGRADEon tmp.sal between SALGRADE.LOSAL and SALGRADE.HISALorder by tmp.sal
--把工资大于1500的所有员工按部门分组,
--按升序输出最后两个平均工资小于3000的部门名称,人数,平均工资,平均工资水平
select dept.dname as "部门名称", tmp.number as "部门人数", tmp.avg_sal as "平均工资", SALGRADE.GRADE as "平均给工资水平"from(select top 2 deptno as "dept_no", COUNT(*) as "number", AVG(sal) as "avg_sal"from emp where sal>1500 group by deptnohaving AVG(sal)<3000order by AVG(sal) desc) "tmp"join depton tmp.dept_no=dept.deptnojoin SALGRADEon tmp.avg_sal between SALGRADE.LOSAL and SALGRADE.HISALorder by tmp.avg_sal
order by
的顺序应该在最后,因此可以用别名。group by
和having
都不可以用别名
外连接
不但返回满足条件的所有记录,而且会返回部门不满足条件的记录。
左外连接
select * from empleft join depton emp.deptno=dept.deptno
- 用左表的一行分别和右表的所有行进行连接,如果没有匹配的行,则一起输出,如果右表有多行匹配,则结果输出多行。如果没有匹配行,则结果只输出一行,该输出左边为左表的一行的内容,右边全部输出
null
- 因为右边很可能出现有多行和左表的某一行匹配,所以左连接产生的结果集的行数很可能大于左边表的行数
select * from deptleft join empon dept.deptno=emp.deptno --16行
返回一个事物和该事物的相关信息,如果没有相关信息,就输出空
右外连接
同左外连接
完全连接
full join
- 两个表中匹配的所有行记录
- 左表中那些在右表找不到匹配的行的记录,右边为
NULL
- 右表中那些在左表找不到匹配的行的记录,左边为
NULL
交叉连接
cross join
等价于join on 1=1
,后面不用加on
自连接
一张表和自己连接起来,注意连接自己的时候需要标明是哪一张表中的字段
--求薪水最高的员工的信息select *from empwhere sal = (select MAX(sal) from emp)-- 不准用聚合函数,求薪水最高的员工的信息
select *from empjoin (select top 1 EMPNO from emp order by sal desc) "tmp"on emp.EMPNO=tmp.EMPNOselect *from empwhere sal not in (select distinct E1.salfrom emp as "E1"join emp as "E2"on E1.sal < E2.sal)
联合
纵向连接表中的数据,即添加一行
--输出每个员工的姓名,工资,上司的姓名select E1.ename as "姓名", E1.sal as "工资", E2.ename as "上司"from emp as "E1"left join emp as "E2" --用左连接的原因是有一个没有上司on E1.mgr = E2.EMPNO--或者使用联合select E1.ename as "姓名", E1.sal as "工资", E2.ename as "上司"from emp as "E1"join emp as "E2"on E1.mgr = E2.EMPNO
union
select ename, sal, 'BOSS' from emp where mgr is null
注意:
select
子句输出列数相等- 数据类型也相同,至少是兼容的
分页查询
SQL Server【三】连接查询相关推荐
- SQL SERVER 跨服务器查询
方法一: 用OPENDATASOURCE 下面是个跨SQLServer查询的示例 Select TableA.*,TableB.* From OPENDATASOURCE( 'SQL ...
- 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许...
*引用*/SQL Server 2000连接中的四个最常见错误: 一."SQL Server 不存在或访问被拒绝" 这个是最复杂的,错误发生的原因比较多,需要检查的方面也比较多. ...
- SQL Server 表连接
目录 SQL Server 内连接 SQL Server 左连接 ON与WHERE子句 SQL Server 右连接 SQL Server 交叉连接 SQL Server自连接 SQL Server全 ...
- SQL Server体系结构——一个查询的生命周期
SQL Server体系结构--一个查询的生命周期(第1部分) 为了缩小读取操作所涉及范围,本文首先着眼于简单的SELECT查询,然后引入执行UPDATE操作有关的附加过程.最后你会读到,优化性能时S ...
- SQL Server 2005 连接本地端口1433开启远程连接/登陆18456错误的解决方法
SQL Server 2005 连接本地端口1433开启远程连接/登陆18456错误的解决方法 出处:http://jimmyli.blog.51cto.com/我站在巨人肩膀上Jimmy Li 作者 ...
- SQL Server无法连接服务器
SQL Server无法连接服务器 情况一:首次安装 1.检查系统服务是否正常 2.检查SQL Server网络配置是否启用 3.双击TCP/IP检查端口是否启用 都检查完了,用telnet 127. ...
- php多表查询性能优化,MSSQL_SQL Server多表查询优化方案集锦,SQL Server多表查询的优化方案是 - phpStudy...
SQL Server多表查询优化方案集锦 SQL Server多表查询的优化方案是本文我们主要要介绍的内容,本文我们给出了优化方案和具体的优化实例,接下来就让我们一起来了解一下这部分内容. 1.执行路 ...
- SQL Server左连接
LEFT JOIN 子句用于查询来自多个表的数据.它返回左表中的所有行和右表中的匹配行. 如果在右表中找不到匹配的行,则使用 NULL 代替显示. 以下图说明了两个结果集的左连接结果: 以下说明如何使 ...
- 在与SQL Server建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且SQL Server已配置为允许远程连接。(provider:命名管道提供程序,
无法连接到(local). 其他信息: 在与SQL Server建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且SQL Server已配置为允许远程连接 ...
- SQL Server T-SQL数据查询
SQL Server T-SQL数据查询 SELECT查询语句 SELECT语句的语法格式 SELECT [ALL|DISTINCT] 列表达式 [INTO 新表名] FROM 表名列表 [WHERE ...
最新文章
- 为什么程序员总是发现不了自己的Bug?
- 关于开发过程中的空指针问题
- TensorRT加速 ——NVIDIA终端AI芯片加速用,可以直接利用caffe或TensorFlow生成的模型来predict(inference)...
- 【WIN10】程序內文件讀取與保存
- Python logging使用
- Python的魔法方法 .
- Linux C高级编程——网络编程之UDP(4)
- android通过点击播放视频,Android通过MediaPlayer实现播放视频实例
- xp的guest访问
- 五险一金 | 2020年企业社保缴费为零问题
- Dubbo-接口数据序列化Serialization
- 黑色渐变遮罩html,巧用CSS遮罩
- elasticsearch删除过期数据
- PCB设计:传输线模型理论
- 计算机网络的形成与发展
- 关键路径问题java_关键路径问题课程设计Java
- 【笔记】学习CSS布局17——column
- 监控宝———开启智能监控新时代
- C3的translate3d代替js动画
- 四种情况会造成内存的泄漏:
热门文章
- Puppeteer入门初探
- static关键字(修饰函数、局部变量、全局变量)
- react.js 从零开始(五)React 中事件的用法
- ASP.NET MVC5 + EF6 入门教程 (5) Model和Entity Framework
- 使用快捷键,快到极致
- 张向东:就以当年期望别人对我们那样的方式
- c++ ptree判断是否存在节点_CTreeCtrl 查找 等于某值 的节点,并设置为高亮
- 51单片机auxr寄存器_MCS-51单片机有几个工作寄存器
- 线性回归csv数据集_测试数据科学家线性回归的30个问题
- mysql数据库应用的权限层级_MySQL数据库的用户权限管理