子查询
select 语句中嵌套select语句,被嵌套的语句称为子查询。
子查询都可以出现在哪里?
select
...(select)
from
...(select)
where
...(select)
- where语句中的子查询
案例:找出比最低工资搞得员工姓名和工资?
select
ename,sal
from
emp
where
sal > min(sal); //会报错
where子句中不能直接使用分组函数
实现思路:
第一步:查询最低工资是多少?
select min(sal)from emp;
第二步:找出>800的
select ename,sal from emp where sal >;
第三步:合并
select ename,sal from emp where sal > (select min(sal)from emp);
from子句中的子查询
注意:from后面的子查询,可以将子查询的查询结果当作一张临时表。
案例:找出每个岗位的平均工资的薪资等级
第一步:找出每个岗位的平均工资(按照高位分组求平均值)
select job,avg(sal)from emp grup by job;
job avg (sal)
ANALYST 300o. ooo000
CLERK 1037.50000o
lMANAGER 2758.333333
PRESIDENT 5000. o000oo
SAL,ESMAN 140o. oooo0o
+-----------4-------------+t表
第二步:克服心理障碍,把以上的查询结果就当作一张真是存在的表t
select * from salgrade; //s表
GRADE lLOSAL lHISAL
1 700 1200
2 1201 1400
3 1401 2000
4 2001 300o
5 3001 9999
------------ s表的losal和s表的hisal
t表和s表进行表连接,条件t表中的avg(sal) between s.losal and s.hisal;
select 从t表中查所有,s表中查grade
t.*, s.grade
from 从t表查
t
join t表和这个表链接
salgrade s
on 条件:t表的avg(sal)字段 between s表中的losal字段 和 s表中hisal字段;
t.avg(sal) between s.losal and s.hisal;
结果会报错,原因是t表不存在
正确语句
select
t.*, s.grade
from 该别名avgsal
(select job,avg(sal) as avgsal from emp group by job) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
+-----------+-------------+-----―
ljob avgsal grade
CLERK 1037.50000o l
SALESMAN 1400.00000o 2
ANALYsT 300o. ooo0oo 4
MANAGER 2758.333333 4
lPRESIDENT 5000. oooooo 5
+-----------+-+-------+
select后面出现子查询
案例:找出每个员工的部门名称,要求显示员工名,部门名?
select
e.enam,e.deptno,(select d.dname from dept d where e.deptno = d.deptno)as dname
from
emp e;
ename deptno ldname
1--------+--------+------------+
SMITH 20 lRESEARCH
ALLEN 30 SALES
WARD 30 SALES
JONES 20 RESEARCH
MARTIN 30 SALES
BL.AKE 30 SALES
CL.ARK 10 ACCOUNTING
sCoTT 20 RESEARCH
KING 10 ACCOUNTING
TURNERl 30 SALES
ADAMS 20 RESEARCH
JAMES 3o SALES
FORD 20 RESEARCH
MILLER 10 ACCOUNTING
select
e.enam,e.deptno,(select dname from dept)as dname
from
emp e;
注意:对于select后面的子查询来说,这个子查询只能一次返回1条结果,对于一条,就报错。
union合并查询结果集
案例:查询工作岗位是MANAGER和SALESMAN的员工
select ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
同于select ename,job from emp where job in ('MANAGER','SALESMAN');
select ename,job from emp where job = 'MANAGER'
union
select ename,job from emp where job = 'SALESMAN';
union的效率要高一些。对于表连接来说,没链接一次新表,
则匹配的次数满足笛卡尔积,成倍得翻。
但是union可以减少匹配的次数。
union在使用的时候有主意事项吗
错误的:union在进行结果集合并的时候,要求两个结果集的列数相同。
select ename,job from emp where job = 'MANAGER'
union
select ename from emp where job = 'SALESMAN'; //会报错
mysql可以,oracle语法不可以,要求:结果集合并时列和列的数据类型也一致。
select ename,job from emp where job = 'MANAGER'
union
select ename,sal from emp where job = 'SALESMAN';
limit
limit是将查询结果集的一部分取出来,通常使用在分页查询当中。
百度默认:一夜显示十条记录。
分页的作用是为了提高用户的体验,因为一次全部都查出来,用户体验差。
可以一页一页翻页看。
limit怎么用?
完整用法:limit startindex,length
startindex是起始下标,length是长度
起始下标从0开始。
缺省用法:limit 5; //这时取前5
按照薪资降序,取出排名在前5名的员工。
select
ename,sal
from
emp
order by
sal desc
limit 5; //取前五
注意:mysql当中limit在order by之后执行!!!
取出工资排名在[3-5]名的员工
select
ename,sal
from
emp
order by
sal desc
limit
2,3;
2表示起始位置从下表2开hi,就是第三条记录
3表示长度
取出工资排名在[5-9]名的员工
select
ename,sal
from
emp
order by
sal desc
limit
4,5;
分页
每页显示3条记录
第一页:limit 0,3 [0 1 2]
第二页:limit 3,3 [3 4 5]
第三页:limit 6,3 [6 7 8]
第四页:limit 9,3 [9 10 11]
每页显示pagesize条记录
第pageNo页:linit (pageNo -1) * pagesize , pagesize
public static void mian(steing[] args){
// 用户提交过来一个页码,以及煤业显示的记录条数
int pageNo = 5; //第5页
int pagesize = 10; //每页显示10条
int starindex = (pageno - 1) * pagesize;
string sql ="select ...limit" + starindex + "," + pagesize;
}
记公式:
limit (pageNo-1)*pagesize,pagesize
关于DQL语句大总结:
select
...
from
...
where
...
group by
...
having
...
order by
...
linit
...
执行顺序:
1.from
2.where
3.group by
4.having
5.select
6.order by
7.limit