说明:DQL(Data Query Language,数据查询语言),用来查询数据库表中的记录。有的书中,会把DQL语言放入到DML(Data Manipulation Language,数据操作语言:数据的增删改)中,不单独拎出来。但既然有拎出来的,也侧面说明了查询语言的丰富。
查询分为:基本查询、条件查询、分组查询、排序查询、分页查询和多表查询,本文介绍多表查询,前五个的介绍参考:http://t.csdn.cn/VUQCS
SQL语句的书写,要按照上述的顺序,不需要的可以跳过,但不能颠倒顺序;
准备工作:创建表,添加数据
-- 部门管理
create table tb_dept(
id int unsigned primary key auto_increment comment '主键ID',
name varchar(10) not null unique comment '部门名称',
create_time datetime not null comment '创建时间',
update_time datetime not null comment '修改时间'
) comment '部门表';
insert into tb_dept
(id, name, create_time, update_time) values
(1,'学工部',now(),now()),
(2,'教研部',now(),now()),
(3,'咨询部',now(),now()),
(4,'就业部',now(),now()),
(5,'人事部',now(),now());
-- 员工管理
create table tb_emp (
id int unsigned primary key auto_increment comment 'ID',
username varchar(20) not null unique comment '用户名',
password varchar(32) default '123456' comment '密码',
name varchar(10) not null comment '姓名',
gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
image varchar(300) comment '图像',
job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
entrydate date comment '入职时间',
dept_id int unsigned comment '部门ID',
create_time datetime not null comment '创建时间',
update_time datetime not null comment '修改时间'
) comment '员工表';
insert into tb_emp
(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) values
('1','sanmao','sm1234','三毛','2','sanmao.jpg','4','2000-01-01','2',now(),now()),
('2','dufu','df1234','杜甫','1','dufu.jpg','2','2015-01-01','2',now(),now()),
('3','libai','lb1234','李白','1','libai.jpg','2','2008-05-01','2',now(),now()),
('4','luxun','lx1234','鲁迅','1','luxun.jpg','2','2007-01-01','2',now(),now()),
('5','tuo','tuo123','陀翁','1','tuoweng.jpg','2','2012-12-05','2',now(),now()),
('6','maerkesi','ma1234','马尔克斯','1','ma.jpg','3','2013-09-05','1',now(),now()),
('7','sate','sa1234','萨特','1','sa.jpg','1','2005-08-01','1',now(),now()),
('8','jiamiu','jia123','加缪','1','jia.jpg','1','2014-11-09','1',now(),now()),
('9','liqingzhao','li1234','李清照','2','li.jpg','1','2011-03-11','1',now(),now()),
('10','tangbohu','tang12','唐伯虎','1','tang.jpg','1','2013-09-05','1',now(),now()),
('11','huang','huang123','黄蓉','1','huang.jpg','5','2007-02-01','3',now(),now()),
('12','guojing','123456','郭靖','1','guo.jpg','5','2008-08-18','3',now(),now()),
('13','zhangfei','123456','张飞','1','zhang.jpg','5','2012-11-01','3',now(),now()),
('14','guanyu','123456','关羽','1','guan.jpg','2','2002-08-01','2',now(),now()),
('15','zhaoyun','123456','赵云','1','zhao.jpg','2','2011-05-01','2',now(),now()),
('16','liubei','123456','刘备','1','liu.jpg','2','2007-01-01','2',now(),now()),
('17','sunshangxiang','123456','孙尚香','2','sun.jpg',NULL,'2015-03-21',NULL,now(),now());
直接查询多表,查询的结果是两表记录的组合,叫做笛卡尔积;
select * from tb_dept, tb_emp;
这样的结果显然是没有意义的,查询出来的数据,并不是实际的结果,而是表明了两张表记录组合产生的可能结果,多表查询就是在这些结果中,寻找出自己真正需要的记录。
连接查询,是用多表之间具有联系的字段,查询出想要的结果,分为内连接和外连接。在上面建立的员工表中的dept_id字段,关联了部门表中的主键,即,tb_emp.dept_id=tb_dept.id。
(1)内连接:字段值的交集;
隐式内连接:查询员工的姓名,及所属的部门名称;
select tb_emp.name, tb_dept.name from tb_emp, tb_dept
where tb_emp.dept_id=tb_dept.id;
可给表设置别名,简化SQL语句
select e.name, d.name from tb_emp e, tb_dept d
where e.dept_id=d.id;
显示内连接(inner可以省略):查询员工的姓名,及所属的部门名称;
select e.name, d.name from tb_emp e
inner join tb_dept d on e.dept_id = d.id
where e.name='张飞';
inner可以省略
select e.name, d.name from tb_emp e
join tb_dept d on e.dept_id = d.id
where e.name='张飞';
(2)外连接:查询的不仅有交集的数据,还包含左/右表中剩下没有交集的数据,如果没有对应上的,用null来代替;
左外连接:查询员工表所有员工的姓名,和对应的部门名称;
select e.name, d.name from tb_emp e
left join tb_dept d on e.dept_id = d.id;
右外连接:查询部门所有部门的名称,和对应的员工名称;
select e.name, d.name from tb_emp e
right join tb_dept d on e.dept_id = d.id;
隐式内连接、显示内连接,只是在SQL语句的书写上有区别,会一种就行;
左外连接、右外连接通过更换查询表的顺序,可以做到互换,如左外连接,想达到右外连接的结果,把表的位置互换就行。
根据子查询返回的结果,可分为标量子查询、列子查询、行子查询和表子查询,SQL语句的特点是“嵌套”,可以称之为“嵌套查询”,子查询是指嵌套在查询语句内的select语句,可以理解为完成本次查询需要的条件。
(1)标量子查询:查询 “教研部”的所有员工信息;
select * from tb_emp where dept_id=
# 子查询结果为单个值
(select id from tb_dept where name='教研部');
(2)列子查询:查询“教研部”和“学工部”的所有员工信息;
select * from tb_emp where dept_id in
# 子查询结果为一列
(select id from tb_dept where name in ('学工部', '教研部'));
(3)行子查询:查询与“鲁迅”的入职日期及职位都相同的员工信息;
select * from tb_emp where (entrydate, job) =
# 子查询结果为单行
(select entrydate, job from tb_emp where name='鲁迅');
(4)表子查询:子查询返回的结果为多行多列(表)
select t.name, t.entrydate, d.name
# 子查询结果为表
from (select * from tb_emp where entrydate>'2006-01-01') t, tb_dept d
where t.dept_id=d.id;