取平均值:avg
mysql> select avg(sal) from emp;
+-------------+
| avg(sal) |
+-------------+
| 2073.214286 |
+-------------+
1 row in set (0.60 sec)
最大值:max
取记录数:count
mysql> select count(sal) from emp;
+------------+
| count(sal) |
+------------+
| 14 |
+------------+
1 row in set (0.04 sec)
mysql> select distinct job from emp;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+
5 rows in set (0.09 sec)
统计公司一共有几个工作岗位
mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
| 5 |
+---------------------+
1 row in set (0.00 sec)
通过哪个或者哪些字段进行分组
若一条DQL语句中有group by子句,那么select关键字后面只能跟参与分组的字段和分组函数(比如ename这些是不可以的,不是分组字段)
1、找出每个工作岗位的最高薪水
分析:先按照工作岗位分组,再使用max求每组最高记录
mysql> select job,max(sal) from emp group by job;
+-----------+----------+
| job | max(sal) |
+-----------+----------+
| ANALYST | 3000.00 |
| CLERK | 1300.00 |
| MANAGER | 2975.00 |
| PRESIDENT | 5000.00 |
| SALESMAN | 1600.00 |
+-----------+----------+
5 rows in set (0.00 sec)
2、计算每个部门的平均薪水
mysql> select
-> deptno,avg(sal) as avgsal
-> from
-> emp
-> group by
-> deptno;
+--------+-------------+
| deptno | avgsal |
+--------+-------------+
| 10 | 2916.666667 |
| 20 | 2175.000000 |
| 30 | 1566.666667 |
+--------+-------------+
3 rows in set (0.00 sec)
3、计算不同工作岗位的最高薪水
mysql> select
-> deptno,job,avg(sal) as avgsal
-> from
-> emp
-> group by
-> deptno,job;
+--------+-----------+-------------+
| deptno | job | avgsal |
+--------+-----------+-------------+
| 10 | CLERK | 1300.000000 |
| 10 | MANAGER | 2450.000000 |
| 10 | PRESIDENT | 5000.000000 |
| 20 | ANALYST | 3000.000000 |
| 20 | CLERK | 950.000000 |
| 20 | MANAGER | 2975.000000 |
| 30 | CLERK | 950.000000 |
| 30 | MANAGER | 2850.000000 |
| 30 | SALESMAN | 1400.000000 |
+--------+-----------+-------------+
9 rows in set (0.04 sec)
找出每个工作岗位的最高薪水,除manager之外
mysql> select
-> job,avg(sal)
-> from
-> emp
-> group by
-> job
-> having
-> avg(sal)>1500;
+-----------+-------------+
| job | avg(sal) |
+-----------+-------------+
| ANALYST | 3000.000000 |
| MANAGER | 2758.333333 |
| PRESIDENT | 5000.000000 |
+-----------+-------------+
3 rows in set (0.09 sec)
注意上面为什么不能用where,因为where关键字后面不能用分组函数,分组函数必须在分组完成后执行,而分组要group by。而group by在where后执行
一般情况尽量在where中过滤,实在无法过滤的数据,通常是需要先分组之后再过滤,此时可以选择having,这牵扯到效率问题
select
...
from 从某张表中检索数据
...
where 经过某条件进行过滤
...
group by 分组
...
having 分组之后不满意再过滤
...
order by 排序输出
...
以上关键字顺序不能改变,严格遵守
以下是执行顺序
1、from
2、where
3、group by
4、having
5、select
6、order by
外连接的查询结果都是一直大于等于内连接的查询结果
会发生总记录是两张表记录乘积(此现象是笛卡尔积现象,为了避免该现象发生,必须在表连接时候加上限制)
1、内连接(等值连接)—————查询每个员工所在的部门名称,要求最终显示员工名和对应的部门名(两张表:员工表(部门号)、部门表(部门号))
SQL92语法:(属于内连接中的等值连接)(缺点:表连接与过滤同时了,结构不清晰)
mysql> select
-> e.ename,d.dname
-> from
-> emp e,dept d
-> where
-> e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
14 rows in set (0.15 sec)
SQL99语法(inner可以省略)(好处:表连接与过滤分离,在最后加where即可过滤,结构清晰)
mysql> select
-> e.ename,d.dname
-> from
-> emp e
-> inner join
-> dept d
-> on
-> e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
14 rows in set (0.00 sec)
2、内连接(非等值连接,SQL99)————找出每一个员工对应的工资等级,要求显示员工名,工资,工资等级(两张表:员工表,工资等级表(salgrade))
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 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
14 rows in set (0.03 sec)
3、内连接(自连接,SQL99)——找出每个员工的上级领导,要求显示员工名以及对应的领导名(一张表看成两张表)
以下是员工表,表中也有员工序号和对应上级的序号,即可看出两张表
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO
+-------+--------+-----------+------+------------+---------+---------+--------
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10
+-------+--------+-----------+------+------------+---------+---------+--------
14 rows in set (0.00 sec)
mysql> select
-> a.ename as empname,b.ename as leadername
-> from
-> emp a
-> join
-> emp b
-> on
-> a.mgr=b.empno;
+---------+------------+
| empname | leadername |
+---------+------------+
| 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)
SQL92语法就是将join改成’,’,on改成where
4、外连接(右连接)——找出每个员工对应的部门名称,要求部门名称全部显示(部分多出来的记录将用null与其匹配)(左连接的话将dept和emp换个位置就好)
mysql> select
-> e.ename,d.dname
-> from
-> emp e
-> right outer join
-> dept d
-> on
-> e.deptno=d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
| NULL | OPERATIONS |
+--------+------------+
15 rows in set (0.05 sec)
5、找出每个员工对应的领导名,要求显示所有的员工
mysql> select a.ename empname,b.ename leadername from emp a join emp b on a.mgr=
b.empno;
+---------+------------+
| empname | leadername |
+---------+------------+
| 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)
(多张表)6、找出每个员工对应的部门名称,以及该员工对应的部门名称,工资等级。要求显示员工名、部门名、工资等级
多张表进行表连接的语法格式(a,b,c表)
原理:a与b连接后,再a与c连接
select
...
from
a
join
b
on
条件
join
c
on
条件;
mysql> select e.ename,d.dname,s.grade from emp e join dept d on e.deptno=d.deptn
o 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 |
+--------+------------+-------+
14 rows in set (0.05 sec)
因为区分内连接和外连接依靠的不是这些关键字,而是看SQL语句中是否存在left/right,若存在,标识一定是个外连接,其他都是内连接
增强可读性
子查询就是嵌套的select语句(select语句嵌套select语句)
找出薪水比公司平均薪水高的员工,要求显示员工名和薪水
第一步找出公司的平均水平
select avg(sal) from emp;
第二步找出薪水大于平均薪水的员工信息
mysql> select ename,sal from emp where sal>(select avg(sal) from emp);
+-------+---------+
| ename | sal |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
6 rows in set (0.00 sec)
找出每个部门的平均薪水,并找出平均薪水的薪水等级
第一步找出每个部门的平均薪水
mysql> select avg(sal) as avgsal from emp group by deptno;
第二步将上面的查询结果当做临时表t,t表和salgrade s表进行表连接,条件:t.avgsal between s.losal and s.hisal
mysql> select
-> t.deptno,t.avgsal,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;
+--------+-------------+-------+
| deptno | avgsal | grade |
+--------+-------------+-------+
| 30 | 1566.666667 | 3 |
| 10 | 2916.666667 | 4 |
| 20 | 2175.000000 | 4 |
+--------+-------------+-------+
3 rows in set (0.12 sec)
显示员工名与其对应的部门名
mysql> select e.ename,(select d.dname from dept d where e.deptno=d.deptno) as dn
ame 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)