1.排序(默认升序)
按照工资升序,找出员工名和薪资
select
ename,sal
from
emp
order by
sal;
注意:默认是升序。怎么指定升序或者降序呢?asc表示升序,desc表示降序。
select ename , sal from emp order by sal; // 升序
select ename , sal from emp order by sal asc; // 升序
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 = ‘SALESMAN’
order by
sal desc;
执行顺序
select
字段 3
from
表名 1
where
条件 2
order by
… 4
order by是最后执行的。
2.分组函数
count 计数
sum 求和
avg 平均值
max 最大值
min 最小值
记住:所有的分组函数都是对“某一组”数据进行操作的。
找出工资总和?
select sum(sal) from emp;
找出最高工资?
select max(sal) from emp;
找出最低工资?
select min(sal) from emp;
找出平均工资?
select avg(sal) from emp;
找出总人数?
select count(*) from emp;
select count(ename) from emp;
分组函数一共5个。
分组函数还有另一个名字:多行处理函数。
多行处理函数的特点:输入多行,最终输出的结果是1行。
分组函数自动忽略NULL:
select sum(comm) from emp where comm is not null; // 不需要额外添加这个过 滤 条件。sum函数自动忽略NULL。
找出工资高于平均工资的员工?
select avg(sal) from emp; // 平均工资
±------------+
| avg(sal) |
±------------+
| 2073.214286 |
±------------+
select ename,sal from emp where sal > avg(sal); //ERROR 1111 (HY000): Invalid use of group function
原因:SQL语句当中有一个语法规则,分组函数不可直接使用在where子句当中。why????
因为group by是在where执行之后才会执行的。
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..
那怎么解决?
第一步:找出平均工资
select avg(sal) from emp;
第二步:找出高于平均工资的员工
select ename,sal from emp where sal > (select avg(sal) from emp);
分组函数也能组合起来用:
select count(*),sum(sal),avg(sal),max(sal),min(sal) from emp;
+----------+----------+-------------+----------+----------+
| count(*) | sum(sal) | avg(sal) | max(sal) | min(sal) |
+----------+----------+-------------+----------+----------+
| 14 | 29025.00 | 2073.214286 | 5000.00 | 800.00 |
+----------+----------+-------------+----------+----------+
3.单行处理函数:
4.count()和count(具体的某个字段)的区别
count():不是统计某个字段中数据的个数,而是统计总记录条数。(和某个字段无关)
count(comm): 表示统计comm字段中不为NULL的数据总数量。
5.group by 和 having
group by : 按照某个字段或者某些字段进行分组。
having : having是对分组之后的数据进行再次过滤。
案例:找出每个工作岗位的最高薪资。
select max(sal),job from emp group by job;
注意:分组函数一般都会和group by联合使用,这也是为什么它被称为分组函数的原因。并且任何一个分组函数(count sum avg max min)都是在group by语句执行结束之后才会执行的。
当一条sql语句没有group by的话,整张表的数据会自成一组。
select ename,max(sal),job from emp group by job;
以上在mysql当中,查询结果是有的,但是结果没有意义,在Oracle数据库当中会报错。语法错误。Oracle的语法规则比MySQL语法规则严谨。
***记住一个规则:当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段。
每个工作岗位的平均薪资?
select job,avg(sal) from emp group by job;
多个字段能不能联合起来一块分组?
案例:找出每个部门不同工作岗位的最高薪资。
select
deptno,job,max(sal)
from
emp
group by
deptno,job;
找出每个部门的最高薪资,要求显示薪资大于2900的数据。
第一步:找出每个部门的最高薪资
select max(sal),deptno from emp group by deptno;
第二步:找出薪资大于2900
select max(sal),deptno from emp group by deptno having max(sal) > 2900; // 这种方式效率低。
select max(sal),deptno from emp where sal > 2900 group by deptno; // 效率较高,建议能够使用where过滤的尽量使用where。
找出每个部门的平均薪资,要求显示薪资大于2000的数据。
第一步:找出每个部门的平均薪资
select deptno,avg(sal) from emp group by deptno;
第二步:要求显示薪资大于2000的数据
select deptno,avg(sal) from emp group by deptno having avg(sal) > 2000;
where后面不能使用分组函数:
select deptno,avg(sal) from emp where avg(sal) > 2000 group by deptno; // 错误了。
这种情况只能使用having过滤。
6.总结一个完整的DQL语句怎么写?
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..
7.关于查询结果集的去重?
mysql> select distinct job from emp; // distinct关键字去除重复记录。
mysql> select ename,distinct job from emp;
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。
mysql> select distinct deptno,job from emp;
deptno和job两个联合起来去重
案例:统计岗位的数量?
select count(distinct job) from emp;
8.连接查询
8.1、什么是连接查询?
在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。
在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
stuno stuname classno classname
-----------------------------------------------------------------------------------
1 zs 1 北京大兴区亦庄经济技术开发区第二中学高三1班
2 ls 1 北京大兴区亦庄经济技术开发区第二中学高三1班
…
学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复,导致数据的冗余。
8.2 连接查询的分类?
根据语法出现的年代来划分的话,包括:
SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administrator,数据库管理员)
SQL99(比较新的语法)
根据表的连接方式来划分,包括:
内连接:
等值连接
非等值连接
自连接
外连接:
左外连接(左连接)
右外连接(右连接)
全连接(这个不讲,很少用!)
8.3 在表的连接查询方面有一种现象被称为:笛卡尔积现象。(笛卡尔乘积现象)
案例:找出每一个员工的部门名称,要求显示员工名和部门名。
EMP表
±-------±-------+
| ename | deptno |
±-------±-------+
| SMITH | 20 |
| ALLEN | 30 |
| WARD | 30 |
| JONES | 20 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| SCOTT | 20 |
| KING | 10 |
| TURNER | 30 |
| ADAMS | 20 |
| JAMES | 30 |
| FORD | 20 |
| MILLER | 10 |
±-------±-------+
DEPT表
±-------±-----------±---------+
| DEPTNO | DNAME | LOC |
±-------±-----------±---------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
±-------±-----------±---------+
select ename,dname from emp,dept;
±-------±-----------+
| ename | dname |
±-------±-----------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
| ALLEN | ACCOUNTING |
| ALLEN | RESEARCH |
| ALLEN | SALES |
| ALLEN | OPERATIONS |
…
56 rows in set (0.00 sec)
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。
关于表的别名:
select e.ename,d.dname from emp e,dept d;
表的别名有什么好处?
第一:执行效率高。
第二:可读性好。
8.4 怎么避免笛卡尔积现象?当然是加条件进行过滤。
思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
不会,次数还是56次。只不过显示的是有效记录。
8.5 内连接之等值连接:最大特点是:条件是等量关系。
案例:查询每个员工的部门名称,要求显示员工名和部门名。
SQL92:(太老,不用了)
select
e.ename,d.dname
from
emp e, dept d
where
e.deptno = d.deptno;
SQL99:(常用的)
select
e.ename,d.dname
from
emp e
join
dept d
on
e.deptno = d.deptno;
// inner可以省略的,带着inner目的是可读性好一些。
select
e.ename,d.dname
from
emp e
inner join
dept d
on
e.deptno = d.deptno;
语法:
…
A
join
B
on
连接条件
where
…
SQL99语法结构更清晰一些:表的连接条件和后来的where条件分离了。