多表查询


#显示雇员名,雇员工资及所在部门的名字#雇员名,雇员工资来自 emp表#部门的名字来自 dept 表#当我们需要指定某个表的列:表.列名SELECT ename,sal,dnameFROM emp,deptWHERE emp.deptno = dept.deptno
#显示员工姓名,工资,工资级别#姓名,工资来自emp 工资级别来自salgradeSELECT ename,sal,gradeFROM emp,salgradeWHERE sal BETWEEN losal AND hisal;
自连接
自连接是指在同一张表的连接查询
#显示公司员工名字和他上级的名字#员工名字在emp表中,上级的名字也在emp中,两者通过emp中的mgr列关联SELECT worker.ename AS '职员名', boss.ename AS '上级名'FROM emp worker, emp bossWHERE worker.mgr = boss.empno #职员上司的编号#自连接的特点:# 1. 把同一张表当作两张表使用# 2. 需要给表取别名(一个worker表,一个boss表)
子查询
子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询
单行子查询
指只返回一行数据的子查询语句 使用 = 接收返回值
#如何显示与smith在同一部门的所有员工#1. 先查询到smith的部门号#2. 把上面的select语句当作一个子查询来使用SELECT deptnoFROM empWHERE ename = 'smith';SELECT *FROM empWHERE depto = (SELECT deptnoFROM empWHERE ename = 'smith')
多行子查询
返回多行数据的子查询,使用关键字 in 接收返回值
#查询和部门10工作内容相同的员工的 名字、岗位、工资、部门号#但是不包括部门10的员工# 1. 查询到10号部门有哪些工作 (不能重复,因此用distinct)# 2. 把上面查询的结果当作子查询使用SELECT DISTINCT jobFROM empWHERE deptno = 10;SELECT ename,job,sal,deptnoFROM empWHERE job IN (SELECT DISTINCT jobFROM empWHERE deptno = 10) AND deptno != 10 #部门不为10
子查询临时表
可以将子查询当作一张临时表使用
#查询ecshop中各个类别,价格最高的商品#先得到各个类别中,价格最高的商品 (max, group by cat_id) 当作临时表SELECT cat_id,MAX(shop_price)FROM ecshopGROUP BY cat_id#获得编号+对应的最高价格SELECT goods_id,ecshop.cat_id,goods_name,shop_price #注意要声明哪个表中的cat_idFROM (SELECT cat_id,MAX(shop_price)FROM ecshopGROUP BY cat_id) temp , ecshop #temp是临时表的名字,从临时表和总表中查找WHERE temp.cat_id = ecshop.cat_idAND temp.max_pricr = ecshop.shop_price#满足编号相同,价格是最大的,输出信息
all 和 any
#显示工资比部门30 的所有员工的工资高 的员工的姓名、工资和部门号SELECT ename,sal,deptnoFROM empWHERE sal > ALL(SELECT salFROM EMPWHERE deptno = 30) #嵌套查询 ,查出所有部门30员工的工资#注:也可以把ALL 改成 MAX
#显示工资比部门30 的其中一个工资高 的员工的姓名、工资和部门号SELECT ename,sal,deptnoFROM empWHERE sal > ANY(SELECT salFROM EMPWHERE deptno = 30) #嵌套查询 ,查出所有部门30员工的工资#注:也可以把ANY 改成 MIN
多列子查询
WHERE (字段1,字段2…) = (子查询语句)
#多列子查询返回多个列数据#查询与smith部门和岗位完全相同的所有雇员(不包括smith本人)SELECT deptno , jobFROM empWHERE ename = 'smith' #得到smith的岗位和工作#把上面的查询当作子查询来使用,并且使用多列子查询的语法来匹配SELECT *FROM empWHERE (deptno,job) = (SELECT deptno , jobFROM empWHERE ename = 'smith') AND ename != 'smith'
一些练习
#查找每个部门工资高于本部门平均工资的人的资料#1.先得到每个部门的部门号和对应的平均工资SELECT deptno,AVG(sal) AS avg_salFROM empGROUP BY deptno #用部门号进行分组#2. 把上面的结果当作子查询,和emp进行多表查询SELECT ename,sal,temp.avg_sal,emp.deptnoFROM emp,(SELECT deptno,AVG(sal) AS avg_salFROM empGROUP BY deptno)tempWHERE emp.deptno = temp.deptno AND emp.sal > temp.avg_sal
#查询每个部门的信息和人员数量#部门信息在dept表(部门名,编号,地址)#各个部门的人员数量 -> 构建一个临时表SELECT COUNT(*),deptnoFROM empGROUP BY deptnoSELECT dname,dept.deptno,loc,tmp.per_num AS '人数'#也可以把 deptno和per_num 合并写成 tmp.*FROM dept, (SELECT COUNT(*),deptnoFROM empGROUP BY deptno) tmpWHERE dept.deptno = tmp.deptno
注:在多表查询中,当多个表的列名不重复时,才可以直接写列名(不然会引起误解)。
合并查询
SELECT expression1, expression2, ... expression_n FROM tables[WHERE conditions]UNION [ALL | DISTINCT]SELECT expression1, expression2, ... expression_n FROM tables[WHERE conditions];

SELECT ename,sal,job FROM emp WHERE sal >2500UNION ALL #查询结果合并,不会去重 DISTINCT会去重SELECT ename,sal,job FROM emp WHERE job = 'MANAGER'#合并两条 SELECT语句的结果
外连接
列出部门名称和这些部门的员工名称和工作,同时要求 显示出那些没有员工的部门,这个无法用多表查询得到(因为无法关联起来)
左外连接 left join 左侧的表完全显示。 右外连接 right join 右侧的表完全显示。
#使用左外连接实现SELECT dname,ename,jobFROM dept LEFT JOIN empON dept.deptno = emp.deptno#使用右外连接实现SELECT dname,ename,jobFROM emp RIGHT JOIN deptON dept.deptno = emp.deptno
自增长
添加后,该字段从1开始自动增长。
CREATE TABLE t24(id INT PRIMARY KEY AUTO_INCREMENT);
#修改默认的自增长开始值ALTER TABLE t24 AUTO_INCREMENT = 100

