将两个表或者两个以上的表以一定的连接条件连接起来,从中检索出满足条件的数据。

内连接

使用inner joininner可以省略

-- 查询员工的姓名和部门名称
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
--实际中发现无论将哪个表放在前面,总是用行数少的表匹配行数多的

fromjoin后面可以使用别名,如果在这里使用别名,其他的地方也都必须使用别名。区别于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

nullnot in在一起的时候需要注意。如果表中有null,则使用not in的时候返回的总为空。

这与SQL的比较机制有关。在SQL中比较结果分为true``false``null,只有结果为true的时候系统才认为匹配成功并返回记录,in的本质是等于的ornot in的本质是不等于的and

比较结果 and null or null
true null true
false false null
null null null

当使用in的时候因为是or进行连接,所以可以正常返回true,在not in的时候是and连接,因此返回总为null,因此返回为空。

详细原因可以看这篇文章:传送门。为了解决这个问题我们可以使用is [not] nullisnull()函数组合判断

--求出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 byhaving都不可以用别名

外连接

不但返回满足条件的所有记录,而且会返回部门不满足条件的记录。

左外连接

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【三】连接查询相关推荐

  1. SQL SERVER 跨服务器查询

    方法一: 用OPENDATASOURCE 下面是个跨SQLServer查询的示例 Select TableA.*,TableB.* From OPENDATASOURCE(          'SQL ...

  2. 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许...

    *引用*/SQL Server 2000连接中的四个最常见错误: 一."SQL Server 不存在或访问被拒绝" 这个是最复杂的,错误发生的原因比较多,需要检查的方面也比较多. ...

  3. SQL Server 表连接

    目录 SQL Server 内连接 SQL Server 左连接 ON与WHERE子句 SQL Server 右连接 SQL Server 交叉连接 SQL Server自连接 SQL Server全 ...

  4. SQL Server体系结构——一个查询的生命周期

    SQL Server体系结构--一个查询的生命周期(第1部分) 为了缩小读取操作所涉及范围,本文首先着眼于简单的SELECT查询,然后引入执行UPDATE操作有关的附加过程.最后你会读到,优化性能时S ...

  5. SQL Server 2005 连接本地端口1433开启远程连接/登陆18456错误的解决方法

    SQL Server 2005 连接本地端口1433开启远程连接/登陆18456错误的解决方法 出处:http://jimmyli.blog.51cto.com/我站在巨人肩膀上Jimmy Li 作者 ...

  6. SQL Server无法连接服务器

    SQL Server无法连接服务器 情况一:首次安装 1.检查系统服务是否正常 2.检查SQL Server网络配置是否启用 3.双击TCP/IP检查端口是否启用 都检查完了,用telnet 127. ...

  7. php多表查询性能优化,MSSQL_SQL Server多表查询优化方案集锦,SQL Server多表查询的优化方案是 - phpStudy...

    SQL Server多表查询优化方案集锦 SQL Server多表查询的优化方案是本文我们主要要介绍的内容,本文我们给出了优化方案和具体的优化实例,接下来就让我们一起来了解一下这部分内容. 1.执行路 ...

  8. SQL Server左连接

    LEFT JOIN 子句用于查询来自多个表的数据.它返回左表中的所有行和右表中的匹配行. 如果在右表中找不到匹配的行,则使用 NULL 代替显示. 以下图说明了两个结果集的左连接结果: 以下说明如何使 ...

  9. 在与SQL Server建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且SQL Server已配置为允许远程连接。(provider:命名管道提供程序,

    无法连接到(local). 其他信息: 在与SQL Server建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且SQL Server已配置为允许远程连接 ...

  10. SQL Server T-SQL数据查询

    SQL Server T-SQL数据查询 SELECT查询语句 SELECT语句的语法格式 SELECT [ALL|DISTINCT] 列表达式 [INTO 新表名] FROM 表名列表 [WHERE ...

最新文章

  1. 为什么程序员总是发现不了自己的Bug?
  2. 关于开发过程中的空指针问题
  3. TensorRT加速 ——NVIDIA终端AI芯片加速用,可以直接利用caffe或TensorFlow生成的模型来predict(inference)...
  4. 【WIN10】程序內文件讀取與保存
  5. Python logging使用
  6. Python的魔法方法 .
  7. Linux C高级编程——网络编程之UDP(4)
  8. android通过点击播放视频,Android通过MediaPlayer实现播放视频实例
  9. xp的guest访问
  10. 五险一金 | 2020年企业社保缴费为零问题
  11. Dubbo-接口数据序列化Serialization
  12. 黑色渐变遮罩html,巧用CSS遮罩
  13. elasticsearch删除过期数据
  14. PCB设计:传输线模型理论
  15. 计算机网络的形成与发展
  16. 关键路径问题java_关键路径问题课程设计Java
  17. 【笔记】学习CSS布局17——column
  18. 监控宝———开启智能监控新时代
  19. C3的translate3d代替js动画
  20. 四种情况会造成内存的泄漏:

热门文章

  1. Puppeteer入门初探
  2. static关键字(修饰函数、局部变量、全局变量)
  3. react.js 从零开始(五)React 中事件的用法
  4. ASP.NET MVC5 + EF6 入门教程 (5) Model和Entity Framework
  5. 使用快捷键,快到极致
  6. 张向东:就以当年期望别人对我们那样的方式
  7. c++ ptree判断是否存在节点_CTreeCtrl 查找 等于某值 的节点,并设置为高亮
  8. 51单片机auxr寄存器_MCS-51单片机有几个工作寄存器
  9. 线性回归csv数据集_测试数据科学家线性回归的30个问题
  10. mysql数据库应用的权限层级_MySQL数据库的用户权限管理