--1 子查询
如果子查询和表连接都实现的时候,推荐用表连接实现( 一般:能用表连接实现的就用表连接,有些情况用表连接不能 或者不易实现的再选择子查询) 系统:缓存,执行计划技术手段 --1 where 条件后 + 子查询 注意: 1 先执行的是子查询语句 2 子查询嵌套的层数越大,性能会随之递减 A) 当子查询写在比较运算符之后(=,!=,>,...)时 要求:子查询的查询结果不能多于1个(1,0(不会报错, 没有结果)) --eg select * from EMP where SAL>(select sal from emp where EMPNO=7369 ) B) 当子查询的查询结果多于1个的时候, 使用 in,exists 存在, 关键字 ----------------------------------------- --in子查询 --查询工作部门是销售部,研发部的员工 select * from EMP where DEPTNO in( select deptno from DEPT where DNAME='sales' or DNAME='research') 思考:in子查询不适合子查询的查询结果特别多的情况 --eg : 查询有员工的部门,并显示部门信息。 --1 表连接 select d.* from EMP e,DEPT d where e.DEPTNO=d.DEPTNO --查询没有员工的部门 (下面的语句是获取不到的) select d.* from EMP e,DEPT d where e.DEPTNO!=d.DEPTNO --(笛卡尔积-相等的) --2 子查询查询没有员工的部门 select * from DEPT where DEPTNO not in( select distinct DEPTNO from EMP) 思考: not in 是所有子查询中效率最差的,所以能 少用就少用。 -------------------------------------------- --exists 子查询 exists(select) 返回 boolean 判断查询结果是否存在 (select * from EMP where DEPTNO=10 )true ,false 短路的行为:查询语句不需要执行出查询结果的,一旦 查询条件为true,那么select语句就结束,exists就返回true --常见应用 --自动 --思路: --如果有此数据库 if(exists(select name from sysdatabases where name='testdb')) drop database testdb --先删除 create database testdb -- 创建 --------------------------------------------- 创建表 :自动化(如果有此表,删除再创建, 否则直接创建) select * from sysobjects where name='tab' if (not exists( select * from sysobjects where name='tab')) create table tab(id int ,name varchar(20)) else begin drop table tab create table tab(id int ,name varchar(20)) end -- 查询有员工的部门,并显示部门信息。 --exists 子查询 select * from DEPT where exists(select * from EMP where DEPTNO=DEPT.DEPTNO ) 思考: exists 不适合的是外部查询的数据量巨大 in 不适合子查询的数据量巨大 not in 是效率的最差的子查询 当外部查询与子查询数据量相当的时候in,exists 子查询的效率也相差不大。 -- EG:用子查询实现,查询emp表中的第6到第10个员工 --(分页的基础)(特别提醒:员工编号唯一,但不一定连续) --不考虑效率 in 子查询 select top 5 * from EMP where EMPNO not in(select top 5 EMPNO from emp) ------------------------------------- --2 在from 之后使用子查询(数据来源) select from 表|视图|结果集(子查询) --eg:查询所有销售部工作的员工信息 select 部门名称,ename from(select ENAME,SAL,JOB,DNAME 部门名称 , LOC部门所在地 from EMP,DEPT where EMP.DEPTNO=DEPT.DEPTNO)as t --必须有别名 where 部门名称 ='sales' ---------------------------------------- --3 在增删改操作中嵌入子查询的案例 --A)insert +select 1) 增加多行 insert into tab_name.... select * union select * union select ... 2) 向现有表备份数据 insert into new_tab select * from old_tab --B) update +select --eg1 员工smith要调换工作部门到 销售部(sales), --编写修改语句实现smith的工作调转 update EMP set DEPTNO=(select deptno from DEPT where DNAME='sales') where ENAME='smith' --C) delete +select --eg2 删除所有研发部的员工(研发部的部门名称是 --research) delete from EMP where DEPTNO=(select deptno from DEPT where DNAME='research') --综合练习:分页查询 用子查询实现,查询emp表中的第6到第10个员工 (分页的基础)(特别提醒:员工编号唯一,但不一定连续) --不考虑效率 in 子查询 --效率低 select top 5 * from EMP where EMPNO not in(select top 5 EMPNO from emp) --效率更好的 分页子查询(row_number) 开窗函数: row_number()over(排序是由需求决定的) 生成有序结果集并添加行号列。 select * from (select ROW_NUMBER() over(order by empno desc)as 行号, * from EMP ) t where 行号 between 6 and 10
---------t_sql 语法