day3:
1.多表查询 实质上是单表查询
多张表连接成一张表时会产生笛卡尔积
如何消除笛卡尔积:连接条件(放在where语句)如果有n张表的连接,至少需要n-1个连接条件才可以完全消除笛卡尔积?
连接方式:
1)等连接:连接条件使用=连接
常用主键的值等于外键的值
例一:查询所有员工的ID,名字,和所在部门的名称
步骤一:分析查询的表
s_emp,s_dept
步骤二:连接条件
s_emp.dept_id=s_dept.id;
步骤三:写sql语句
select s_emp.id,s_emp.last_name,s_dept.name
from s_emp,s_dept
where s_emp.dept_id=s_dept.id;
注意:给表取别名 每个字段使用表的别名区分 多表查询一定不要忘记了连接条件
例二:查询员工的名字和部门所在地区的名称(3张表)
步骤一:分析查询的表
s_emp,s_dept,s_region
步骤二:连接条件
s_emp.dept_id=s_dept.id
s_dept.region_id=s_region_id
步骤三:写sql语句
select s_emp.last_name,s_region.name,s_dept.name,s_region.id
from s_emp,s_dept,s_region
where s_emp.dept_id=s_dept.id and
s_dept.region_id=region_id;
练习一:查询部门名称包含sa的员工姓名薪水
select s_dept.name,s_emp.last_name,s_emp.salary
from s_dept,s_emp
where s_emp.dept_id=s_dept.id and lower(s_dept.name) like ‘%sa%’;
注意:多表查询先写连接条件后写限定性条件
练习二:查询在欧洲销售部门的薪水在1000到2000的员工信息
select s_emp.last_name,s_emp.salary,s_dept.name,s_region.name
from s_emp,s_dept,s_region
where s_emp.dept_id=s_dept.id and
s_dept.region_id=s_region.id and s_region.name = ‘Europe’ and s_dept.name=‘Sales’ and s_emp.salary between 1000 and 2000;
2)不等连接
查询所有员工的工资等级
select e.last_name,g.name
from s_emp e ,s_gender g
where e.salary between g.minsal and g.maxsal;
3)外连接:把外键为空的数据一并查询出来
注意:等连接不能查询外键值为空的数据
使用:(+)
规则:(+)放在查询数据少的一方
例一:查询员工所在部门的名称,包括没有部门号的员工(所有员工)
select s_emp.last_name,s_dept.name
from s_emp,s_dept
where s_emp.dept_id=s_dept.id(+);
例二:查询所有员工所在部门的名称,但是需要把所有部门给查询出来
select s_emp.last_name,s_dept.name
from s_emp,s_dept
where s_emp.dept_id(+)=s_dept.id;
例三:查询员工所在部门的名称,没有部门号的员工,所有的部门都查询出来
error…一个谓词只能引用一个外部联接的表
select s_emp.last_name,s_dept.name
from s_emp,s_dept
where s_emp.dept_id(+)= s_dept.id(+);
这里只能用标准的sql语句:full join…on…(全外连接)
select e.last_name,d.name
from s_dept d full join s_emp e
on e.dept_id = d.id;
左外连接:(+)放在等号的右边
标准的sql:…left jion … on …左外连接
右外连接:(+)放在等号的左边
标准的sql:…right join …on…右外连接
select e.last_name,d.name
from s_emp e right join s_dept d on e,.dept_id=d.id;
4)子连接:连接的时候来自同一张表
同一张表可以当作多张表使用
查询所有员工的经理的last_name,salary
包括没有经理的员工
select w.last_name,m.last_name,m.salary
from s_emp w,s_emp m
where w.manager_id = m.id;
5)集合操作符
union:并集,重复的列只显示一行
union all:并集,不会消除重复的行
minus:差集
intersect:交集
rownum:伪列,可以分页技术,逻辑位置,只能等于1
不能大于或者大于等于任何正整数
可以小于或者小于等于任何正整数
分页技术:
第一页:显示前10条
第二页:显示第11到20条
第三页:显示第21到30条
rownum :数据在表中逻辑位置,从1开始进行递增
rowid:数据在表中物理位置
select rownum,rowid,last_name
from s_emp;
查询部门表中的前三条数据
select *
from s_dept
where rownum <=3;
查询部门表这第4条数据到第6条数据
使用前6条数据减去前3条数据
select *
from s_dept
where rownum <=6
minus
select *
from s_dept
where rownum <=3;
组函数,聚合函数:n行数据处理之后可能只能一行数据
常用的聚合函数有:
avg:求平均值
count:计算有多少条数据
max:求最大值
min:求最小值
sum:求和
例一:查询所有员工的平均值,最高工资,最低工资,工资总和,有多少个员工
select avg(salary),max(salary),min(salary),sum(salary),count(*)
from s_emp;
例二:查询每个部门的平均工资?对平均工资进行降序排序,平均工资大于1400
分组:group by ---->值相同的数据分为一组
select dept_id,avg(salary)
from s_emp
group by dept_id
having avg(salary)>1400
order by avg(salary) desc;
注意:1)group by进行分组,值相同的数据分为一组放在where后
2)对组函数1进行过滤使用having,在where中不能出现组函数 放在group by后
3)出现在select后的字段,如果该字段没有放在组函数中,就必须放在group by 后
4)多个字段进行同时分组,多个字段的值同时相同才分为一组
sql执行流程:sql引擎解析sql语句
select----- 5
from----- 1
where---- 2
group by---- 3
having----- 4
order by---- 6
单值函数:n行数据处理之后还是n行数据
子查询:
一条sql语句嵌套一个或者多个sql语句
格式:
select …
from …
where 字段名 比较符(
select …
from …
where …
group by…
having …
order by …
)
grop by …
having …
order by…
什么情况下使用:比较符中参数不确定的情况下
子查询出现的地方:1)where子句
2)from子句
3)having子句