DQL:(Data Query Language)数据查询语言
目录
单表查询
一、去除重复记录
使用distinct
关键字
select distinct 字段名 from表名:
注
:
- distinct 只对查询结果进行去重,原表数据不会被修改。
- distinct 后面可以跟多个字段,表示多个字段联合去重。
mysql> select distinct job,deptno from emp order by deptno;
+-----------+--------+
| job | deptno |
+-----------+--------+
| CLERK | 10 |
| MANAGER | 10 |
| PRESIDENT | 10 |
| ANALYST | 20 |
| CLERK | 20 |
| MANAGER | 20 |
| CLERK | 30 |
| MANAGER | 30 |
| SALESMAN | 30 |
+-----------+--------+
9 rows in set (0.01 sec)
二、连接查询
1. 笛卡尔积现象
当两张表进行连接查询时,如果没有任何条件的限制会发生笛卡尔积现象。如emp表有14条记录,dept表有4条记录,不加任何条件直接在两表查询最终会显示56条数据。
mysql> select ename,dname from emp,dept;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | OPERATIONS |
| SMITH | SALES |
| SMITH | RESEARCH |
| SMITH | ACCOUNTING |
| ALLEN | OPERATIONS |
......
| MILLER | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
56 rows in set (0.00 sec)
可以通过添加条件避免笛卡尔积现象的发生。
mysql> select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
......
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.01 sec)
2. 内连接
select ... from A inner join B on A和B的连接条件 where 筛选条件;
说明:
- inner可以省略,带着inner可读性更好
- 内连接的特点:
AB两表之间没有主次关系
,将完全能够满足连接条件的数据查询出来。
2.1 等值连接
on 后面的连接条件是等量关系。
案例:查询员工的部门名称。
mysql> select e.ename,d.dname from emp e inner join dept d on e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
......
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.01 sec)
2.2 非等值连接
连接条件不是等量关系。
案例:查询每个员工的薪资等级。
mysql> select e.ename,e.sal,s.grade from emp e
> join salgrade s on e.sal between s.losal and s.hisal;
+--------+---------+-------+
| ename | sal | grade |
+--------+---------+-------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
......
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
14 rows in set (0.01 sec)
2.3 自连接
将一张表看做是两张表。
案例:查询员工的上级领导并显示。
mysql> select e.ename,m.ename from
> (select empno,ename from emp) as m
> join emp e on e.mgr=m.empno;
+--------+-------+
| ename | ename |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
13 rows in set (0.00 sec)
3. 外连接
两张表具有主次关系。
语句中的outer可以省略。
3.1 左外连接
select ... from A left outer join B on 连接条件;
说明:将join关键字左边的表看做是主表,左表中的数据将被全部查询出来,右表中不满足条件的数据使用NULL填充。
mysql> select e.ename,d.dname from dept d
> left join emp e on e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| MILLER | ACCOUNTING |
| KING | ACCOUNTING |
| CLARK | ACCOUNTING |
| FORD | RESEARCH |
| ADAMS | RESEARCH |
| SCOTT | RESEARCH |
| JONES | RESEARCH |
| SMITH | RESEARCH |
| JAMES | SALES |
| TURNER | SALES |
| BLAKE | SALES |
| MARTIN | SALES |
| WARD | SALES |
| ALLEN | SALES |
| NULL | OPERATIONS |
+--------+------------+
15 rows in set (0.00 sec)
3.2 右外连接
select ... from A right outer join B on 连接条件;
说明:将join关键字右边的表看做是主表,右表中的数据将被全部查询出来,左表中不满足条件的数据使用NULL填充。
mysql> select e.ename,d.dname from emp e
> right join dept d on e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| MILLER | ACCOUNTING |
| KING | ACCOUNTING |
| CLARK | ACCOUNTING |
| FORD | RESEARCH |
| ADAMS | RESEARCH |
| SCOTT | RESEARCH |
| JONES | RESEARCH |
| SMITH | RESEARCH |
| JAMES | SALES |
| TURNER | SALES |
| BLAKE | SALES |
| MARTIN | SALES |
| WARD | SALES |
| ALLEN | SALES |
| NULL | OPERATIONS |
+--------+------------+
15 rows in set (0.01 sec)
案例:查询所有员工(包括KING)的上级领导并显示员工名和领导名。
mysql> select e.ename,m.ename from emp e
-> left join (select empno,ename from emp) m
-> on e.mgr=m.empno;
+--------+-------+
| ename | ename |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| KING | NULL |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
14 rows in set (0.00 sec)
4.三表联查,四表联查…
select ... from A join B on AB连接条件 join C on AC连接条件 right join D on AD连接条件...;
案例1:查询每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级。
mysql> select e.ename,d.dname,e.sal,s.grade from emp e
-> join dept d on e.deptno=d.deptno
-> join salgrade s on e.sal between s.losal and s.hisal;
+--------+------------+---------+-------+
| ename | dname | sal | grade |
+--------+------------+---------+-------+
| SMITH | RESEARCH | 800.00 | 1 |
| ALLEN | SALES | 1600.00 | 3 |
| WARD | SALES | 1250.00 | 2 |
| JONES | RESEARCH | 2975.00 | 4 |
| MARTIN | SALES | 1250.00 | 2 |
| BLAKE | SALES | 2850.00 | 4 |
| CLARK | ACCOUNTING | 2450.00 | 4 |
| SCOTT | RESEARCH | 3000.00 | 4 |
| KING | ACCOUNTING | 5000.00 | 5 |
| TURNER | SALES | 1500.00 | 3 |
| ADAMS | RESEARCH | 1100.00 | 1 |
| JAMES | SALES | 950.00 | 1 |
| FORD | RESEARCH | 3000.00 | 4 |
| MILLER | ACCOUNTING | 1300.00 | 2 |
+--------+------------+---------+-------+
14 rows in set (0.01 sec)
案例2: 查询每个员工的领导名,部门名称,工资以及工资等级。
mysql> select e.ename,m.ename mname,d.dname,e.sal,s.grade from emp e
-> left join (select empno,ename from emp) as m on e.mgr=m.empno
-> join dept d on e.deptno=d.deptno
-> join salgrade s on e.sal between s.losal and s.hisal;
+--------+-------+------------+---------+-------+
| ename | mname | dname | sal | grade |
+--------+-------+------------+---------+-------+
| SMITH | FORD | RESEARCH | 800.00 | 1 |
| ALLEN | BLAKE | SALES | 1600.00 | 3 |
| WARD | BLAKE | SALES | 1250.00 | 2 |
| JONES | KING | RESEARCH | 2975.00 | 4 |
| MARTIN | BLAKE | SALES | 1250.00 | 2 |
| BLAKE | KING | SALES | 2850.00 | 4 |
| CLARK | KING | ACCOUNTING | 2450.00 | 4 |
| SCOTT | JONES | RESEARCH | 3000.00 | 4 |
| KING | NULL | ACCOUNTING | 5000.00 | 5 |
| TURNER | BLAKE | SALES | 1500.00 | 3 |
| ADAMS | SCOTT | RESEARCH | 1100.00 | 1 |
| JAMES | BLAKE | SALES | 950.00 | 1 |
| FORD | JONES | RESEARCH | 3000.00 | 4 |
| MILLER | CLARK | ACCOUNTING | 1300.00 | 2 |
+--------+-------+------------+---------+-------+
14 rows in set (0.00 sec)
三、 子查询
select语句中嵌套select语句,称为子查询。
1. where中的子查询
上一篇文章中提到where子句中不能直接使用分组函数,可以使用子查询解决这个问题。
案例: 查询比最低工资高的员工姓名和工资。
mysql> select ename,sal from emp
-> where sal>(select min(sal) from emp);
+--------+---------+
| ename | sal |
+--------+---------+
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
13 rows in set (0.01 sec)
2. from后的子查询
注
:from后面的子查询,可以将子查询结果当作一张临时表。
案例:查询每个岗位的平均工资的薪资等级。
mysql> select a.job,a.avgsal,s.grade from
-> (select job,round(avg(sal),2) avgsal from emp group by job) a
-> join salgrade s on a.avgsal between s.losal and s.hisal;
+-----------+---------+-------+
| job | avgsal | grade |
+-----------+---------+-------+
| CLERK | 1037.5 | 1 |
| SALESMAN | 1400 | 2 |
| MANAGER | 2758.33 | 4 |
| ANALYST | 3000 | 4 |
| PRESIDENT | 5000 | 5 |
+-----------+---------+-------+
5 rows in set (0.00 sec)
3. select后的子查询(了解)
案例:查询员工的所属部门。
mysql> select e.ename,(select d.dname from dept d where e.deptno=d.deptno) dname from emp e;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
注
:对于select后的子查询来说,一次返回一条数据,多于一条会报错。
四、union 合并查询结果
有ABC三张表,各有10条记录
A 连接 B 连接 C ----- 匹配次数:10*10*10 = 1000次
------------------------------------------------------------------
A 连接 B ----- 匹配次数: 10*10 = 100次
A 连接 C ----- 匹配次数: 10*10 = 100次
使用union合并:100+100 = 200次
案例: 查询工作岗位是MANAGER和SALESMAN的员工。
mysql> select ename,job from emp where job='manager' or job='salesman';
mysql> select ename,job from emp where job in ('manager','salesman');
以上两条语句是利用之前提到的知识写出来的,结果相同。
mysql> select ename,job from emp where job='manager'
-> union
-> select ename,job from emp where job='salesman';
注:union在进行结果合并时,要求两个结果集的列数相同。在书写语句时查询字段顺序书写要保持一致。
union的查询效率更高,对于表连接来说,每连接一次新表,匹配的次数满足笛卡尔积,也就是说查询次数会成倍增长,但是union会减少查询次数,同时将查询结果集进行拼接输出。
五、 分页查询
1. limit(start,len)
说明:
- 将查询结果的一部分取出来。
- start:起始下标,可以省略,默认从0开始。
- len:截取长度。
- mysql中limit在order by后面执行
案例: 查询工资排名前3-5的员工。
mysql> select ename,sal from emp order by sal desc limit 2,3;
+-------+---------+
| ename | sal |
+-------+---------+
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
3 rows in set (0.00 sec)
2. 通用分页
每页显示pageSize条记录,第pageNo页
公式:limit (pageNo-1) * pageSize,pageSize
DQL总结
1. 查询语句书写顺序
select ...from ...
where ...
group by ... having ...
order by ... limit...
2. 执行顺序
- from
- where
- group by
- having
- select
- order by
- limit