查询
这篇文章是来自于B站动力节点的MySQL视频 链接动力节点-MySQL_MySQL教程
不过这个视频可能不是很新了(因为用的是txt排版…)
下面是相关的表数据
mysql> desc dept; (部门表)
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| DEPTNO | int(2) | NO | PRI | NULL | | 部门编号
| DNAME | varchar(14) | YES | | NULL | | 部门名称
| LOC | varchar(13) | YES | | NULL | | 部门位置
+--------+-------------+------+-----+---------+-------+
mysql> desc emp;(员工表)
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO | int(4) | NO | PRI | NULL | | 员工编号
| ENAME | varchar(10) | YES | | NULL | | 员工姓名
| JOB | varchar(9) | YES | | NULL | | 工作岗位
| MGR | int(4) | YES | | NULL | | 上级领导编号
| HIREDATE | date | YES | | NULL | | 入职日期
| SAL | double(7,2) | YES | | NULL | | 月薪
| COMM | double(7,2) | YES | | NULL | | 补助/津贴
| DEPTNO | int(2) | YES | | NULL | | 部门编号
+----------+-------------+------+-----+---------+-------+
mysql> desc salgrade; (工资等级表)
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| GRADE | int(11) | YES | | NULL | | 等级
| LOSAL | int(11) | YES | | NULL | | 最低薪资
| HISAL | int(11) | YES | | NULL | | 最高薪资
+-------+---------+------+-----+---------+-------+
条件查询
找出工资在1100-3000的员工,包括1100,3000
select ename,sal from where sal >= 1100 and sal <= 3000;
select ename,sal from emp where sal between 1100 and 300;//闭区间
可以用于字符串:
select ename from emp where ename between 'A' and 'C';//左闭右开
找出哪些人津贴为NULL或0:
select ename,sal,comn from emp where comn is null or comn = 0;//is not null;
注意:运算符的优先级不确定的时候加小括号:
找出薪资大于1000的并且部门编号是20或30部门的员工。
select ename,sal,deptno from emp where sal > 1000 and (deptno = 20 or deptno = 30);
in等同于or:表示集合
找出工作岗位是MANAGER和SALESMAN的员工?
select ename,job from emp where job = 'SALEMAM' or job = 'MANAGER';
select ename,job from emp where job in ('SALEMAM','MANAGER');//in后面的值不是区间,是具体的值
not in :不在这几个值当中。
模糊查询like
- %代表任意多个字符,_代表任意一个字符
select ename from emp where ename like '%O%';
select ename from emp where ename like '%\_%';//转义字符(含_的)
select ename from emp where ename like '%T';//名字中最后一个为T
排序order by
默认是升序asc,desc表示降序
select ename , sal from emp order by sal;
select ename , sal from emp order by 2;//按第二列排
select ename , sal from emp order by sal desc;
按照工资的降序排列,当工资相同的时候再按照名字的升序排列:
select ename,sal from emp order by sal desc , ename asc;//前面的占主导地位,前面相等再调用后面的。
例如:找出工作岗位是SALESMAN的员工,并要求按照薪资的降序排列。
select
ename,job,sal
from
emp
where
job = 'SALEMAN'
order by
sal desc;
分组函数
多行处理函数;都是对“某一组”数据进行操作的。
- count 计数
- count(distinct job)–distinct(去重)
- sum 求和
- avg 平均
- max
- min
记住:所有的分组函数都是对“某一组”数据进行操作的。
select sum(sal) from emp;==>忽略NULL
select count(*) from emp;//总人数ename
select sum(comm) from emp;
select sum(comm) from emp where comm is not null; // 不需要额外添加这个过滤条件。sum函数自动忽略NULL。
- 分组函数自动忽略NULL
- 数学计算含NULL,则结果为NULL
- ifnull(可能为NULL 的数据,被当作什么处理) ,单行处理函数。
- 分组函数还有另一个名字:多行处理函数。
多行处理函数的特点:输入多行,最终输出的结果是1行。
//ifnull() 空处理函数
ifnull(可能为NULL的数据,被当做什么处理) : 属于单行处理函数。
select ename ,ifnull(comn,0) as comn from emp;
//计算每个员工的年薪
select ename ,(sal+ifnull(comn,0))*12 as yearsal from emp;
找出工资大于平均工资的员工:
select ename,sal from emp where sal > avg(sal);//ERROR
//1.找出平均工资 2.找出高于平均工资的员工
select ename ,sal from emp where sal > (select avg(sal) from emp);//子查询
注意:SQL语句中的分组函数不可以直接使用在where子句当中
==>因为group by 是在where后面执行
//一个完整的SQL语句:
select 5
..
from 1
..
where 2
..//无法用分组函数
group by 3 之后才能用分组函数
..
having 4
..
order by 6
..
count(*)与count(某个字段)
-
count(*) :不是统计某个字段中数据的个数,而是统计总记录条数。(和某个字段无关)
-
count(comn):表示统计comn字段中不为NULL的数据总数量。
group by 和 having
group by :按照某个字段或者某些字段进行分组。
having:对分组后的数据进行再次过滤。
案例:
找出每个工作岗位的最高薪资
select max(sal),job from emp group by job;
注意:
-
当一条语句中有group by 的话,select后面只能跟分组函数和参与分组的字段
-
分组函数一般都会和group by联合使用,这也是为什么它被称为分组函数的原因。
-
并且任何一个分组函数(count sum avg max min)都是在group by语句执行结束之后才会执行的。
-
当一条sql语句没有group by的话,整张表的数据会自成一组。
select ename ,max(sal),job from group by job;//ERROR
求每个工作岗位的平均薪资:
select job,avg(sal) from emp group by job;
找出每个部门不同工作岗位的最高薪资:(联合分组)
select deptno,job,max(sal) from emp group by deptno,job;
找出每个部门的最高的薪资,要求显示薪资大于2500的数据:分步写
select max(sal),depton from emp group by deptno having max(sal) > 2900;//效率低
select max(sal),depton from emp where sal > 2900 group by deptno;
建议能够使用where过滤的尽量用where
找出每个部门的平均薪资,要求显示薪资大于2500的数据(having对分组数据过滤)
select deptno,avg(sal) from emp group by deptno having avg(sal) > 2500;
总结一个完整的DQL语句怎么写?
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..
// limit 7
关于查询结果集的去重?
select distinct job from emp; // distinct关键字去除重复job记录。
记住:distinct只能出现在所有字段的最前面。
统计岗位的数量?
select count(distinct job) from emp;
连接查询
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。
select
e.ename,d.dname
from
emp e
join //inner join
dept d
on
e.deptno = d.deptno;
内连接之非等值连接
INNER JOIN
只会保留两个表都存在的数据(还记得之前的交集吗),这看起来意味着一些数据的丢失,在某些场景下会有问题.
最大的特点是:连接条件中的关系是非等量关系。
找出每个员工的工资等级,要求显示员工名、工资、工资等级。
select
e.ename,e.sal,s.grade
from
emp e
join // inner可以省略
salgrade s
on
e.sal between s.losal and s.hisal;
自连接
最大的特点是:一张表看做两张表。自己连接自己。
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
员工的领导编号 = 领导的员工编号
select
a.ename as '员工名',b.ename as '领导名'
from
emp a
inner join
emp b
on
a.mgr = b.empno;
外连接
内连接:
假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
AB两张表没有主副之分,两张表是平等的。
外连接:
假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
外连接的分类?
左外连接(左连接):表示左边的这张表是主表。
右外连接(右连接):表示右边的这张表是主表。
外连接最重要的特点是:主表的数据无条件的全部查询出来。
找出哪个部门没有员工?
select
d.*
from
emp e
right join
dept d
on
e.deptno = d.deptno
where
e.empno is null;
三张表的连接查询
…
A
join
B
join
C
on
…表示:A表和B表先进行表连接,连接之后A表继续和C表进行连接。
案例:找出每一个员工的部门名称以及工资等级:
select
e.ename,d.dname,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 | grade |
+--------+------------+-------+
| SMITH | RESEARCH | 1 |
| ALLEN | SALES | 3 |
| WARD | SALES | 2 |
| JONES | RESEARCH | 4 |
| MARTIN | SALES | 2 |
| BLAKE | SALES | 4 |
| CLARK | ACCOUNTING | 4 |
| SCOTT | RESEARCH | 4 |
| KING | ACCOUNTING | 5 |
| TURNER | SALES | 3 |
| ADAMS | RESEARCH | 1 |
| JAMES | SALES | 1 |
| FORD | RESEARCH | 4 |
| MILLER | ACCOUNTING | 2 |
+--------+------------+-------+
找出每一个员工的部门名称、工资等级、以及上级领导。<把上面的合起来>
select
e.ename '员工',d.dname,s.grade,e1.ename '领导'
from
emp e
join
dept d
on
e.deptno = d.deptno
join
salgrade s
on
e.sal between s.losal and s.hisal
left join
emp e1
on
e.mgr = e1.empno;
子查询
1. where子句中使用子查询
案例:找出高于平均薪资的员工信息。
select * from emp where sal > (select avg(sal) from emp);
2. from后面嵌套子查询
找出每个部门平均薪水的等级。
第一步:找出每个部门平均薪水(按照部门编号分组,求sal的平均值)
select deptno,avg(sal) as avgsal from emp group by deptno;
第二步:将以上的查询结果当做临时表t,让t表和salgrade s表连接,条件是:t.avgsal between s.losal and s.hisal
select
t.*,s.grade
from
(select deptno,avg(sal) as avgsal from emp group by deptno) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
找出每个部门平均的薪水等级。
第一步:找出每个员工的薪水等级。
select e.ename,e.sal,e.deptno,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
第二步:基于以上结果,继续按照deptno分组,求grade平均值。
select
e.deptno,avg(s.grade)
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal
group by
e.deptno;
3. 在select后面嵌套子查询
案例:找出每个员工所在的部门名称,要求显示员工名和部门名。
select
e.ename,d.dname
from
emp e
join
dept d
on
e.deptno = d.deptno;
//总和
select
e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname
from
emp e;
union
(可以将查询结果集相加)
案例:找出工作岗位是SALESMAN和MANAGER的员工
select ename,job from emp where job = 'MANAGER'
union
select ename,job from emp where job = 'SALESMAN';
limit
-
limit是mysql特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)
-
limit取结果集中的部分数据,这时它的作用。
-
语法机制:
limit startIndex, length
startIndex表示起始位置,从0开始,0表示第一条数据。
length表示取几个
通用的标准分页sql
每页显示3条记录:
第1页:0, 3
第2页:3, 3
第3页:6, 3
第4页:9, 3
第5页:12, 3
每页显示pageSize条记录:
第pageNo页:(pageNo - 1) * pageSize, pageSize
pageSize是:是每页显示多少条记录
pageNo是:显示第几页
java代码{
int pageNo = 2; // 页码是2
int pageSize = 10; // 每页显示10条
limit (pageNo - 1) * pageSize, pageSize
}