013.子查询和分页子查询(sql实例)

--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 语法

posted @ 2017-01-20 20:30  90后梦想大师  阅读(1163)  评论(0编辑  收藏  举报