一、建表语句
DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;
CREATE TABLE DEPT
(DEPTNO int(2) not null ,
DNAME VARCHAR(14) ,
LOC VARCHAR(13),
primary key (DEPTNO)
);
CREATE TABLE EMP
(EMPNO int(4) not null ,
ENAME VARCHAR(10),
JOB VARCHAR(9),
MGR INT(4),
HIREDATE DATE DEFAULT NULL,
SAL DOUBLE(7,2),
COMM DOUBLE(7,2),
primary key (EMPNO),
DEPTNO INT(2)
)
;
CREATE TABLE SALGRADE
( GRADE INT,
LOSAL INT,
HISAL INT );
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
30, 'SALES', 'CHICAGO');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
40, 'OPERATIONS', 'BOSTON');
commit;
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7369, 'SMITH', 'CLERK', 7902, '1980-12-17'
, 800, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20'
, 1600, 300, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7521, 'WARD', 'SALESMAN', 7698, '1981-02-22'
, 1250, 500, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7566, 'JONES', 'MANAGER', 7839, '1981-04-02'
, 2975, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28'
, 1250, 1400, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01'
, 2850, NULL, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7782, 'CLARK', 'MANAGER', 7839, '1981-06-09'
, 2450, NULL, 10);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19'
, 3000, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7839, 'KING', 'PRESIDENT', NULL, '1981-11-17'
, 5000, NULL, 10);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08'
, 1500, 0, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7876, 'ADAMS', 'CLERK', 7788, '1987-05-23'
, 1100, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7900, 'JAMES', 'CLERK', 7698, '1981-12-03'
, 950, NULL, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7902, 'FORD', 'ANALYST', 7566, '1981-12-03'
, 3000, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7934, 'MILLER', 'CLERK', 7782, '1982-01-23'
, 1300, NULL, 10);
commit;
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
1, 700, 1200);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
2, 1201, 1400);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
3, 1401, 2000);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
4, 2001, 3000);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
5, 3001, 9999);
commit;
二、数据排序asc、desc
含义
排序采用 order by 子句,order by 后面跟上排序字段,排序字段可以放多个,多个采用逗号间隔,order by默认采用升序(asc),如果存在 where 子句,那么 order by 必须放到where 询句后面。
1.按照薪水由小到大排序(系统默认由小到大)
select ename,sal from emp order by sal;
2.取得job为MANAGER的员工,按照薪水由小到大排序(系统默认由小到大)
select ename,job,sal from emp where job = 'MANAGER' order by sal;
3.按照job和薪水倒序排序
select ename,job,ename from emp order by job desc,sal desc;
注:如果采用多个字段排序,如果根据第一个字段排序重复了,会根据第二个字段排序
三、处理函数(单行处理)
1.数据处理函数(单行处理函数)
Lower | 转换小写 |
upper | 转换大写 |
substr | 取子串(substr(被截取的字符串,起始下标,截取的长度)) |
length | 取长度 |
trim | 去空格 |
str_to_date | 将字符串转换成日期 |
date_format | 格式化日期 |
format | 设置干分位 |
round | 四舍五入 |
rand() | 生成随机数 |
ifnull | 可以将null转换成一个具体值 |
2.lower(字段名)函数:转换为小写
用法:lower(要转换的字段)
查询员工姓名,将员工姓名全部转换成小写
select lower(ename) as ename from emp;
3.upper(字段名)函数:转换为大写
用法:upper(要转换字段名称)
查询员工姓名,将员工姓名全部转换成大写
select upper(ename) as ename from emp;
4.substr(字段名,起始下标,截取长度)函数:取子串
用法:substr(字段名,起始下标,截取长度)
注意:起始下标:从1开始
1)查询并显示所有员工姓名的第二个字母
select substr(ename,2,1) from emp;
2)查询员工姓名中第二个字母为A的所有员工
select ename from emp where substr(ename,2,1) = 'A'
5.length(字段名)函数:取字段长度
用法:length(字段名称)
取得员工姓名长度
select ename,length(ename) as nameLength from emp;
6.ifnull(字段名,替换值)函数:空值处理函数
用法:ifnull(字段名称,将要替换)
结论:在数据库中,有NULL参与数学运算的结果一定为NULL;为了防止计算结果出现NULL,建议先使用ifnull函数预先处理
1)查询员工姓名及补助,如果补助为NULL设置为0
select ename,ifnull(comm,0) from emp;
2)查询员工薪水与补助的和
select sal+ifnull(comm,0) from emp;
3)没有补助的员工,将每月补助100,求员工的年薪
select ename,(sal+ifnull(comm,100)) * 12 yearsal from emp;
7.case..when..then..else..end
匹配工作岗位,当MANAGER时,薪水上调10%,当为SALESMAN时,薪水上调50%,其他岗位薪水不变
select ename,sal,job,
(case job
when 'MANAGER' then sal*1.1
when 'SALESMAN' then sal*1.5
else sal
end) as newsal
from
emp;
8.trim(‘字符串’)函数:去除首尾空格
作用:trim函数去除首尾空格,不会去除中间空格
用法:trim(字符串)
取得工作岗位为manager的所有员工
select * from emp where job = trim(' manager ');
9.round(数字,保留小数位数)函数:四舍五入
用法:round(要四舍五入的数字,四舍五入到哪一位),默认保留整数位
10.rand()函数:生成随机数
select round(rand()*100,0);
11.str_to_date函数:将字符串转换为日期
作用:将‘日期字符串’ 转换为 ‘日期类型’数据
用法:str_to_date('日期字符串',‘日期格式’)
日期字符串:日期格式的字符串
日期格式:告知MySQL输入日期字符串的格式是什么
MySQL日期格式:
序号 | 格式符 | 功能 | 格式符 | 功能 | |
1 | %Y | 代表四年的年份 | %y | 代表两位的年份 | |
2 | %m | 代表月,格式(01..12) | %c | 代表月,格式(1...12) | |
3 | %d | 代表日 | |||
4 | %H | 代表24小时制 | %h | 代表12小时制 | |
5 | %i | 代表分钟,格式(00...59) | |||
6 | %S或%s | 代表秒,格式(00..59) |
1)查询出1981-12-03入职的员工
select ename,hiredate from emp where hiredate = '1981-12-03';
原因:
1、在MySQL中日期作为查询条件时:可以使用字符串为其赋值
2、输入的日期字符串格式与MySQL默认日期格式相同
2)查询出02-20-1981入职的员工
select ename,hiredate from emp where hiredate = str_to_date('02-20-1981','%m-%d-%Y');
12.date_format函数:将日期转换为特定格式字符串
作用:‘将日期类型’转换为特定格式的‘日期字符串’类型
用法:date_format(日期类型数据,;'日期格式')
1)查询员工的入职日期,以‘10-12-1980’的格式显示到窗口中
select ename,date_format(hiredate,'%m-%d-%Y') hiredate from emp;
2)查询员工的入职日期,以'10/12/1980'的格式显示到窗口中
select ename,date_format(hiredate,'%m/%d/%Y') hiredate from emp;
结论:date_format函数主要用在数据库查询操作中。实际工作中,客户需要日期以特定格式展示的时候,需要使用该函数
四、分组函数/聚合函数/多行处理函数
1.常见函数
sum | 求和 |
avg | 取平均 |
max | 取最大值 |
min | 取最小值 |
count | 取得记录数 |
2.单行/多行处理函数
单行处理函数:一行输入对应一行输出
多行处理函数:多行输入对应一行输出
注:
1、分组函数自动忽略控制,不需要手动增加where条件排除空值;
2、分组函数不能直接使用在where关键字后面;
3.sum(字段)函数
作用:求某一列的和,null会自动被忽略;
用法:sum(字段名称)
1)取得薪水总计
select sum(sal) from emp;
2)取得补助总计
select sum(comm) from emp;
3)取得总共薪水(工资+补助)合计
select sum(sal + ifnull(comm,0)) from emp
4.avg(字段名)函数
作用:求某一列的平均值,null会被自动忽略
用法:avg(字段名称)
取得平均薪水avg(sal)
select avg(sal) as avgsal from emp
5.max(字段名)函数
作用:取得某一列的最大值
用法:max(字段名称)
1)取得最高薪水max(sal)
select max(sal) from emp;
2)取得最晚入职的员工max(sal)
select max(hiredate) from emp;
6.min(字段名)函数
作用:取得某一列最小值
用法:min(字段名称)
1)取得最低薪水max(sal)
select min(sal) from emp;
2)取得最早入职的员工max(sal)
select min(hiredate) from emp;
7.count函数
作用:取得某字段值不为null的记录总数
用法:count(字段名称)或count(*)
注意:
1、count(*)表示取得当前查询表所有记录
2、count(字段名称),不会统计为null的记录
1)取得所有员工数
select count(*) from emp;
2)取得补助不为空的所有员工数
select count(comm) from emp;
3)取得补助为空的员工数量
select count(*) from emp where comm is null;
8.distinct去除重复记录
作用:将查询结果中某一字段的重复记录去除掉
用法:distinct字段名或distinct 字段名1,字段名2
distinct 字段名A:去除与字段名A相同的记录
distinct字段名A,字段名B:去除与字段A和字段B同时相同的记录
注意:distinct只能出现在所有字段最前面,后面如果有多个字段及为多字段联合去重
1)查询该公司有哪些工作岗位
select distinct job from emp
2)查询该公司工作岗位数量
select count(distinct job) from emp;
3)去除部门编号deptno和工作岗位job重复记录
select distinct deptno,job from emp
9.分组查询:group by
作用:通过哪个或哪些字段进行分组
用法:group by 字段名称
1)找出每个工作岗位的最高薪水
select job,max(sal) from emp group by job
结论:有group by的DDL语句中,select语句后面只能跟分组函数+参与分组的字段
2)计算每个工作岗位的最高薪水,并且按照由低到高进行排序
思路分析:先按照工作岗位job进行分组,然后对每一组薪水求最大值max,最后在根据每一组薪水的最大值进行由低到高排序
select job,max(sal) as maxsal from emp group by job order by maxsal
注意:如果使用了order by,order by必须放到group by 后面
3)计算每个部门的平均薪水
思路分析:首先,按照部门编号分组,然后对每一组的薪水求平均值
select deptno,avg(sal) as avgsal from emp group by deptno
4)计算不同部门不同岗位的最高薪水
思路分析:首先把deptno和job看成一个字段进行联合字段分组,联系到distinct关键字
select dep,job,max(sal) as maxsal from emp group by deptno,job;
5)找出每个工作岗位的最高薪水,出MANAGER之外
思路分析:先将job等于MANAGER的过滤掉,然后再根据工作岗位进行分组,对每一组求最大薪水
select job,max(sal) as maxsal from emp where job <> 'MAXAGER' group by job;
10.having
作用:如果想对分组的数据再进行过滤,需要使用having子句
找出每个工作岗位的平均薪水,要求显示平均薪水大于2000的
思路分析:先对工作岗位job分组,然后对每一组薪水求平均值,最后再对每一组平均薪水的值进行大于2000的条件过滤
select job,avg(sal) from emp group by job having avg(sal) > 2000
11.where与having区别
1)where和having都是为了完成数据的过滤,他们后面都是添加条件
2)where是在group by之前完成过滤
3)having是在group by之后完成过滤
五、select语句总结
一个完整的SQL语句如下:
select
xxxx
from
xxxx
where
xxxx
group by
xxxx
having
xxxx
order by
xxxx
1)from将硬盘上的表文件加载到内存
2)where将符合条件的数据进行摘取出来,生成一张新的临时表
3)group by根据列中的数据种类,将当前临时表划分成若干个新的临时表
4)having可以过滤掉group by生成的不符合条件的临时表
5)select对当前临时表进行整列读取
6)order by对select生成的临时表,进行重新排序,生成新的临时表
7)limit对最终生成的临时表的数据行,进行截取