1.
having子句是用来对分组之后的数据进行过滤
因此使用having时通常都会先使用group by
2.
如果没有使用group by但使用了having则意味着having把所有的记录当做一组来进行过滤
select count(*)
from emp
having avg(sal)>1000
3. having子句出现的字段必须是分组后的整体信息
having子句不允许出现组内的详细信息
4.
尽管select语句中可以出现别名但having语句中不能出现字段的别名,
只能使用最原始的字段
5.
where 和 having的异同
相同: 都是对数据过滤,保留有效的数据
不同: where是对原始的记录过滤,having是对分组后的记录过滤,两者顺序不同
where必须写在having前面,两者顺序不可颠倒,否则编译出错
select deptno,job, avg(sal) "平均工资",count(*) "部门人数",sum(sal) "部门总工资",min(sal) "部门最低工资"
from emp
group by deptno,job
order by deptno;
select comm "奖金", count(*) "人数"
from emp
group by comm;--按照奖金分组
select max(sal) from emp;
--输出部门平均工资大于的部门的编号部门的平均工资
select deptno,avg(sal) "平均工资"
from emp
group by deptno
having avg(sal)>1500;
select deptno,avg(sal) "平均工资"
from emp
group by deptno
having deptno > 10;--true
select deptno,avg(sal) "平均工资"
from emp
group by deptno
having count(*) > 3;--true
select deptno,avg(sal) "平均工资"
from emp
group by deptno
having ename like '%A%';--error
select deptno "部门编号", avg(sal) "平均工资"
from emp
group by deptno
having "部门编号">1;--error
--把名字不包含A的所有的员工按部门分组
--统计输出部门平均工资大于的部门的编号部门的平均工资
select deptno, avg(sal) "平均工资"
from emp
where ename not like '%A%'
group by deptno
having avg(sal) > 2000;
--把工资>2000
--统计输出部门平均工资大于的部门的编号部门的平均工资
select deptno, avg(sal) "平均工资", count(*) "部门工资>2000人数", max(sal) "部门最高工资"
from emp
where sal >2000 --where 是对原始的记录过滤
group by deptno
having avg(sal) > 3000; --对分组之后的记录过滤
select deptno, avg(sal) "平均工资", count(*) "部门工资>2000人数", max(sal) "部门最高工资"
from emp
group by deptno
having avg(sal) > 3000
where sal >2000;--error
--总结:所有select参数的顺序是不允许变化的,否则编译出错
having和where的异同
相同: 都是对数据过滤,保留有效的数据
不同: where是对原始的记录过滤,having是对分组后的记录过滤,两者顺序不同
where必须写在having前面,两者顺序不可颠倒,否则编译出错
select语句的基本结构
select select_list
into new_table_name
from table_list
where search_conditions
group by group_by_list
having search+condition
order by order_list [asc|desc]
select语句基本结构中包含了8个子句,这些子句的排列顺序是固定的。其中除select子句外,其他
子句都可以省略,但若出现必须按照基本结构中的顺序排列。
12、连接查询
定义:
将两个表或者两个以上的表以一定的连接条件连接起来从中检索出满足条件的数据
分类
内连接(重点+难点)
1. select ... from A, B 的用法
产生:
行数 A,B之积
列数:A和B之和
或者说把A表的每一条记录都和B表的每一条记录组合在一起形成一个笛卡尔积
或者说把B表的每一条记录都和A表的每一条记录组合在一起形成一个笛卡尔积
--emp 14行列dept 5行列产生的是一个笛卡尔积行列
--此时无任何连接条件
注意 select * from A,B和select * from B,A是一样的
select * from emp, dept
判断下面两个语句的输出结果是什么:
select *
from emp, dept
where emp.deptno =10--输出的行数肯定是dept表行数的倍数
select *
from emp, dept
where dept.deptno =10--输出的行数肯定是emp表行数的倍数
2. select ... from A, B where ...的用法
对select ... from A, B
例子:
--输出5行11列
select * from emp, dept
where empno = 7369 产生的笛卡尔积用where中的条件进行过滤
3. select ... from A join B on ...的用法
select "E".ename "员工姓名", "D".dname "部门名称"
from emp "E"--E D可以用中文替代
join dept "D" -- join连接
on "E".deptno = "D".deptno --on连接条件on不能省略有join就有on
4.SQL92标准和SQL99标准的区别
select ... from A, B where ... 是SQL92标准
与
select ... from A join B on ... 的比较 是SQL99标准
输出结果一样
推荐使用SQL99标准
1. sql99更容易理解
2. 在sql99标准中on和where可以做不同的分工
on指定连接条件
where对连接后的临时表进行过滤
select *
from emp,dept
where emp.deptno=dept.deptno
--等价于
select *
from emp
join dept
on emp.deptno=dept.deptno
例子:
-- 1.把工资大于的员工姓名和部门名称输出
--sql92的实现
select "E".ename "员工姓名", "D".dname "部门名称"
from emp "E", dept "D"--起别名是用于查询的优化
where "E".sal > 2000 and "E".deptno = "D".deptno
--sql99实现
select "E".ename "员工姓名", "D".dname "部门名称"
from emp "E"
join dept "D"
on "E".deptno = "D".deptno
where "E".sal > 2000
-- 2.把工资大于的员工姓名和部门名称输出和工资等级(三个表连接)
--sql99实现
select "E".ename "员工姓名", "D".dname "部门名称", "S".grade "工资等级"
from emp "E"
join dept "D"
on "E".deptno = "D".deptno
join SALGRADE "S"
on "E".sal >= "S".LOSAL and "E".sal <= "S".HISAL
where "E".sal > 2000
--sql92实现
select "E".ename "员工姓名", "D".dname "部门名称", "S".grade "工资等级"
from emp "E", dept "D", SALGRADE "S"
where "E".deptno = "D".deptno and ("E".sal >= "S".LOSAL and "E".sal <= "S".HISAL)
and "E".sal > 2000
问题:以上where是否可以写在join前面
否 以下查询是错误的
select "E".ename "员工姓名", "D".dname "部门名称", "S".grade "工资等级"
from emp "E"
where "E".sal > 2000
join dept "D"
on "E".deptno = "D".deptno
join SALGRADE "S"
on "E".sal >= "S".LOSAL and "E".sal <= "S".HISAL--erro
select *
from emp, dept
where dept.deptno =10--输出的行数肯定是emp表行数的倍数
--等价于
select *
from emp
join dept
on 1=1
where dept.deptno =10
以下等价错误
select *
from emp
join dept
on emp.deptno=dept.deptno--on指定的是连接条件
having dept.deptno =10-- 错误having是对分组后的数据过滤