MYSQL(多表查询) - G-holic/Java-Web GitHub Wiki

多表查询

* 查询语法:
	select
		列名列表
	from
		表名列表
	where...
* 准备sql
	# 创建部门表
	create table dept(
		id int primary key auto_increment,
		name varchar(20)		
	);
	insert into dept (name) values ('开发部'),('市场部'),('财务部');
	# 创建员工表
	create table emp(
		id int primary key not null auto_increment,
		name varchar(10),
		gender char(1),--性别
		salary double,--工资
		join_date date,--入职日期
		dept_id int,
		foreign key (dept_id) references dept(id)--+外键,关联部门表(部门表的主键)
	);
	INSERT INTO much_table.emp VALUES(1, '孙悟空', '男', 7200.0, '2013-02-24', 1);
	INSERT INTO much_table.emp VALUES(2, '猪八戒', '男', 3600.0, '2010-12-02', 2);
	INSERT INTO much_table.emp VALUES(3, '唐僧', '男', 9000.0, '2008-08-08', 2);
	INSERT INTO much_table.emp VALUES(4, '白骨精', '女', 5000.0, '2015-10-07', 3);
	INSERT INTO much_table.emp VALUES(5, '蜘蛛精', '女', 4500.0, '2011-03-14', 1);
	
* 笛卡尔积:
	* 有两个集合A,B,取这两个集合的所有组成情况。
	* 要完成多表查询,需要先消除无用的数据
* 多表查询的分类:
	1.内连接查询:
		1.隐式内连接:使用where条件消除无用的数据
			*例子:
			-- 查询所有员工信息和对应的部门信息

			select * from emp,dept where emp.dept_id = dept.id ;

			-- 查询员工表的名称,性别。部门表的名称
			select emp.name,emp.gender,dept.name from emp,dept where emp.dept_id = dept.id ;
			select  
				e.name,
				e.gender,
				d.name 
			from 
				emp e ,
				dept d 
			where 
				e.dept_id =d.id ;
		2.显示内连接:
			* 语法:select 字段列表 from 表名1 inner(可省略) join 表名2 on 条件
			* 例如:
				* select * from emp inner join dept on emp.dept_id = dept.id ;
				* select * from emp  join dept on emp.dept_id = dept.id ;
		3.内连接查询:
			1.从哪些表中查询数据?
			2.条件是什么?
			3.查询哪些字段?
	2.外连接查询:
			* 例如:
			-- 查询所有员工信息,如果员工有部门则查询部门名称,如果没有部门,则不显是部门名称
				* select e.*,d.name from emp e left join dept d on e.dept_id = d.id ;
				* select e.*,d.name from dept d right join emp e on e.dept_id = d.id ;
				
		1.左外连接:
			* 语法:select 字段列表 from 表名1 left outer(可省略)join 表名2 on 条件;
			* 查询的是左表所有数据以及其交集部分。
		2.右外连接:
			* 语法:select 字段列表 from 表名1 right outer(可省略)join 表名2 on 条件;
			* 查询的是右表所有数据以及其交集部分。
	3.子查询:
		* 概念:查询中嵌套查询,称嵌套查询为子查询。
			-- 查询工资最高的员工信息
			-- 1.查询最高的工资是多少
			select max(salary) from emp ;
			-- 2.查询员工信息,并且工资等于9000的
			select * from emp where emp.salary = 9000;

			-- 一条sql就完成这个操作。(子查询)
			select * from emp where emp.salary = (select max(salary) from emp);
		
		* 子查询不同情况:
			1.子查询的结果是单行单列的:
				* 子查询可以作为条件,使用运算符去判断。
				* 例如:
				-- 查询员工工资小于平均工资的人
				select * from emp where emp.salary < (select avg(salary) from emp );
			2.子查询的结果是多行单列的:
				* 子查询可以作为条件,使用运算符in来判断。
				* 例如:
				-- 查询'财务部'和'市场部'所有的员工信息
				select id from dept where name = '财务部' or name = '市场部';
				select * from emp where dept_id = 3 or dept_id =2;
				-- 子查询
				select * from  emp where dept_id in (select id from dept where name = '财务部' or name = '市场部');
			3.子查询的结果是多行多列的:
				* 子查询可以作为一张虚拟表参与查询
				-- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
				select * from dept d ,(select * from emp e where e.join_date > '2011-11-11') e where d.id = e.dept_id;
				-- 普通内连接
				select * from emp e ,dept d where e.dept_id = d.id and e.join_date > '2011-11-11';

1. 1. 1.