十、合计/统计函数

10.1 count 函数:返回行的总数

image.png

  1. -- 演示 mysql 的统计函数的使用
  2. -- 统计一个班级共有多少学生?
  3. SELECT COUNT(*) FROM student;
  4. -- 统计数学成绩大于 90 的学生有多少个?
  5. SELECT COUNT(*) FROM student
  6. WHERE math > 90
  7. -- 统计总分大于 250 的人数有多少?
  8. SELECT COUNT(*) FROM student
  9. WHERE (math + english + chinese) > 250
  10. -- count(*) count(列) 的区别
  11. -- 解释 :count(*) 返回满足条件的记录的行数
  12. -- count(列): 统计满足条件的某列有多少个,但是会排除 null 的情况
  13. CREATE TABLE t15 (
  14. `name` VARCHAR(20));
  15. INSERT INTO t15 VALUES('tom');
  16. INSERT INTO t15 VALUES('jack');
  17. INSERT INTO t15 VALUES('mary');
  18. INSERT INTO t15 VALUES(NULL);
  19. SELECT * FROM t15;
  20. SELECT COUNT(*) FROM t15; -- 4
  21. SELECT COUNT(`name`) FROM t15;-- 3

10.2 sum 函数:返回满足 where 条件的列和

一般用在数值列
image.png

  1. -- 演示 sum 函数的使用
  2. -- 统计一个班级数学总成绩?
  3. SELECT SUM(math) FROM student;
  4. -- 统计一个班级语文、英语、数学各科的总成绩
  5. SELECT SUM(math) AS math_total_score,SUM(english),SUM(chinese) FROM student;
  6. -- 统计一个班级语文、英语、数学的成绩总和
  7. SELECT SUM(math + english + chinese) FROM student;
  8. -- 统计一个班级语文成绩平均分
  9. SELECT SUM(chinese)/ COUNT(*) FROM student;
  10. SELECT SUM(`name`) FROM student;

10.3 avg 函数:返回满足 where 条件的一列的平均值

image.png

  1. -- 演示 avg 的使用
  2. -- 练习:
  3. -- 求一个班级数学平均分?
  4. SELECT AVG(math) FROM student;
  5. -- 求一个班级总分平均分
  6. SELECT AVG(math + english + chinese) FROM student;

10.4 max/min 函数:返回满足 where 条件的一列的最大/最小值

image.png

  1. -- 演示 max min 的使用
  2. -- 求班级最高分和最低分(数值范围在统计中特别有用)
  3. SELECT MAX(math + english + chinese), MIN(math + english + chinese)
  4. FROM student;
  5. -- 求出班级数学最高分和最低分
  6. SELECT MAX(math) AS math_high_socre, MIN(math) AS math_low_socre
  7. FROM student;

10.5 使用 group by 子句对列进行分组

image.png

10.6 使用 having 子句对分组后的结果进行过滤

image.png

  1. -- 相关表的创建
  2. -- 部门表
  3. CREATE TABLE dept( /*部门表*/
  4. deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
  5. dname VARCHAR(20) NOT NULL DEFAULT "",
  6. loc VARCHAR(13) NOT NULL DEFAULT ""
  7. );
  8. INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK'),
  9. (20, 'RESEARCH', 'DALLAS'),
  10. (30, 'SALES', 'CHICAGO'),
  11. (40, 'OPERATIONS', 'BOSTON');
  12. SELECT * FROM dept;
  13. -- 员工表
  14. CREATE TABLE emp
  15. (empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
  16. ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
  17. job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/
  18. mgr MEDIUMINT UNSIGNED ,/*上级编号*/
  19. hiredate DATE NOT NULL,/*入职时间*/
  20. sal DECIMAL(7,2) NOT NULL,/*薪水*/
  21. comm DECIMAL(7,2) ,/*红利 奖金*/
  22. deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
  23. );
  24. -- 添加测试数据
  25. INSERT INTO emp VALUES(7369, 'SMITH', 'CLERK', 7902, '1990-12-17', 800.00,NULL , 20),
  26. (7499, 'ALLEN', 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30),
  27. (7521, 'WARD', 'SALESMAN', 7698, '1991-2-22', 1250.00, 500.00, 30),
  28. (7566, 'JONES', 'MANAGER', 7839, '1991-4-2', 2975.00,NULL,20),
  29. (7654, 'MARTIN', 'SALESMAN', 7698, '1991-9-28',1250.00,1400.00,30),
  30. (7698, 'BLAKE','MANAGER', 7839,'1991-5-1', 2850.00,NULL,30),
  31. (7782, 'CLARK','MANAGER', 7839, '1991-6-9',2450.00,NULL,10),
  32. (7788, 'SCOTT','ANALYST',7566, '1997-4-19',3000.00,NULL,20),
  33. (7839, 'KING','PRESIDENT',NULL,'1991-11-17',5000.00,NULL,10),
  34. (7844, 'TURNER', 'SALESMAN',7698, '1991-9-8', 1500.00, NULL,30),
  35. (7900, 'JAMES','CLERK',7698, '1991-12-3',950.00,NULL,30),
  36. (7902, 'FORD', 'ANALYST',7566,'1991-12-3',3000.00, NULL,20),
  37. (7934,'MILLER','CLERK',7782,'1992-1-23', 1300.00, NULL,10);
  38. SELECT * FROM emp;
  39. -- 工资级别
  40. #工资级别表
  41. CREATE TABLE salgrade
  42. (
  43. grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*工资级别*/
  44. losal DECIMAL(17,2) NOT NULL, /* 该级别的最低工资 */
  45. hisal DECIMAL(17,2) NOT NULL /* 该级别的最高工资*/
  46. );
  47. INSERT INTO salgrade VALUES (1,700,1200);
  48. INSERT INTO salgrade VALUES (2,1201,1400);
  49. INSERT INTO salgrade VALUES (3,1401,2000);
  50. INSERT INTO salgrade VALUES (4,2001,3000);
  51. INSERT INTO salgrade VALUES (5,3001,9999);
  52. SELECT * FROM salgrade;
  53. SELECT * FROM dept;
  54. SELECT * FROM emp;
  1. # 演示 group by + having
  2. GROUP by 用于对查询的结果分组统计
  3. -- having 子句用于限制分组显示结果.
  4. -- ?如何显示每个部门的平均工资和最高工资
  5. -- 老韩分析: avg(sal) max(sal)
  6. -- 按照部分来分组查询
  7. SELECT AVG(sal), MAX(sal) , deptno
  8. FROM emp GROUP BY deptno;
  9. -- 使用数学方法,对小数点进行处理
  10. SELECT FORMAT(AVG(sal),2), MAX(sal) , deptno
  11. FROM emp GROUP BY deptno;
  12. -- ?显示每个部门的每种岗位的平均工资和最低工资
  13. -- 老师分析 1. 显示每个部门的平均工资和最低工资
  14. -- 2. 显示每个部门的每种岗位的平均工资和最低工资
  15. SELECT AVG(sal), MIN(sal) , deptno, job
  16. FROM emp GROUP BY deptno, job;
  17. -- ?显示平均工资低于 2000 的部门号和它的平均工资 // 别名
  18. -- 老师分析 [写 sql 语句的思路是化繁为简,各个击破]
  19. -- 1. 显示各个部门的平均工资和部门号
  20. -- 2. 1 的结果基础上,进行过滤,保留 AVG(sal) < 2000
  21. -- 3. 使用别名进行过滤
  22. SELECT AVG(sal), deptno
  23. FROM emp GROUP BY deptno
  24. HAVING AVG(sal) < 2000;
  25. -- 使用别名
  26. SELECT AVG(sal) AS avg_sal, deptno
  27. FROM emp GROUP BY deptno
  28. HAVING avg_sal < 2000;

十一、字符串相关函数

image.png

11.1 CHARSET(str) 返回字串字符集

  1. -- 演示字符串相关函数的使用 使用 emp 表来演示
  2. -- CHARSET(str) 返回字串字符集
  3. SELECT CHARSET(ename) FROM emp;

11.2 CONCAT (string2 [,… ]) 连接字符串

  1. -- CONCAT (string2 [,... ]) 连接字串, 将多个列拼接成一列
  2. SELECT CONCAT(ename, ' 工作是 ', job) FROM emp;

11.3 INSTR 返回 substring 在 string 中出现的位置

  1. -- INSTR (string ,substring ) 返回 substring string 中出现的位置,没有返回 0
  2. -- dual 亚元表, 系统表 可以作为测试表使用
  3. SELECT INSTR('hanshunping', 'ping') FROM DUAL;

11.4 UCASE (string2 ) 转换成大写

  1. -- UCASE (string2 ) 转换成大写
  2. SELECT UCASE(ename) FROM emp;

11.5 LCASE (string2 ) 转换成小写

  1. -- LCASE (string2 ) 转换成小写
  2. SELECT LCASE(ename) FROM emp;
  3. -- LEFT (string2 ,length )从 string2 中的左边起取 length 个字符
  4. -- RIGHT (string2 ,length ) string2 中的右边起取 length 个字符
  5. SELECT LEFT(ename, 2) FROM emp;

11.6 LENGTH (string ) string 长度[按照字节]

  1. -- LENGTH (string ) string 长度[按照字节]
  2. SELECT LENGTH(ename) FROM emp;

11.7 REPLACE 替换字符串内容

  1. -- REPLACE (str ,search_str ,replace_str )
  2. -- str 中用 replace_str 替换 search_str
  3. -- 如果是 manager 就替换成 经理
  4. SELECT ename, REPLACE(job,'MANAGER', '经理') FROM emp;

11.8 STRCMP (string1 ,string2 ) 逐字符比较两字串大小

  1. -- STRCMP (string1 ,string2 ) 逐字符比较两字串大小
  2. SELECT STRCMP('hsp', 'hsp') FROM DUAL;

11.9 SUBSTRING 截取字符串中的内容

  1. -- SUBSTRING (str , position [,length ])
  2. -- str position 开始【从 1 开始计算】,取 length 个字符
  3. -- ename 列的第一个位置开始取出 2 个字符
  4. SELECT SUBSTRING(ename, 1, 2) FROM emp;

11.10 LTRIM RTRIM TRIM 去除首尾空格

  1. -- LTRIM (string2 ) RTRIM (string2 ) TRIM(string)
  2. -- 去除前端空格或后端空格
  3. SELECT LTRIM(' 韩顺平教育') FROM DUAL;
  4. SELECT RTRIM('韩顺平教育 ') FROM DUAL;
  5. SELECT TRIM(' 韩顺平教育 ') FROM DUAL;

练习:以首字母小写的方式显示所有员工 emp 表的姓名

  1. -- 思路:先取出 ename 的第一个字符,转成小写的
  2. -- 把他和后面的字符串进行拼接输出即可
  3. SELECT CONCAT(LCASE(SUBSTRING(ename,1,1)), SUBSTRING(ename,2)) AS new_name
  4. FROM emp;
  5. SELECT CONCAT(LCASE(LEFT(ename,1)), SUBSTRING(ename,2)) AS new_name
  6. FROM emp;

十二、数学相关函数

image.png

12.1 ABS(num) 绝对值

  1. -- ABS(num) 绝对值
  2. SELECT ABS(-10) FROM DUAL;

12.2 BIN (decimal_number )十进制转二进制

  1. -- BIN (decimal_number )十进制转二进制
  2. SELECT BIN(10) FROM DUAL;

12.3 CEILING (number2 ) 向上取整

  1. -- CEILING (number2 ) 向上取整, 得到比 num2 大的最小整数
  2. SELECT CEILING(-1.1) FROM DUAL;

12.4 CONV(number2,from_base,to_base) 进制转换

  1. -- CONV(number2,from_base,to_base) 进制转换
  2. -- 下面的含义是 8 是十进制的 8, 转成 2 进制输出
  3. SELECT CONV(8, 10, 2) FROM DUAL;
  4. -- 下面的含义是 8 16 进制的 8, 转成 2 进制输出
  5. SELECT CONV(16, 16, 10) FROM DUAL;

12.5 FLOOR (number2 ) 向下取整

  1. -- FLOOR (number2 ) 向下取整,得到比 num2 小的最大整数
  2. SELECT FLOOR(-1.1) FROM DUAL;

12.6 FORMAT (number,decimal_places ) 保留小数位数(四舍五入)

  1. -- FORMAT (number,decimal_places ) 保留小数位数(四舍五入)
  2. SELECT FORMAT(78.125458,2) FROM DUAL;

12.7 HEX (DecimalNumber ) 转十六进制

  1. -- HEX (DecimalNumber ) 转十六进制

12.8 LEAST (number , number2 [,..]) 求最小值

  1. -- LEAST (number , number2 [,..]) 求最小值
  2. SELECT LEAST(0,1, -10, 4) FROM DUAL;

12.9 MOD (numerator ,denominator ) 求余

  1. -- MOD (numerator ,denominator ) 求余
  2. SELECT MOD(10, 3) FROM DUAL;

12.10 RAND([seed]) RAND([seed]) 返回随机数 其范围为 0 ≤ v ≤ 1.0

  1. -- RAND([seed]) RAND([seed]) 返回随机数 其范围为 0 v 1.0
  2. -- 老韩说明
  3. -- 1. 如果使用 rand() 每次返回不同的随机数 ,在 0 v 1.0
  4. -- 2. 如果使用 rand(seed) 返回随机数, 范围 0 v 1.0, 如果 seed 不变,
  5. -- 该随机数也不变了
  6. SELECT RAND() FROM DUAL;
  7. SELECT FLOOR(RAND(3)*10) FROM DUAL; -- 3就是一个种子数,生成种子后,同一个种子的随机数不变

十三、时间日期相关函数

image.png

  1. - 日期时间相关函数
  2. -- CURRENT_DATE ( ) 当前日期
  3. SELECT CURRENT_DATE() FROM DUAL;
  4. -- CURRENT_TIME ( )当前时间
  5. SELECT CURRENT_TIME() FROM DUAL;
  6. -- CURRENT_TIMESTAMP ( ) 当前时间戳
  7. SELECT CURRENT_TIMESTAMP() FROM DUAL;
  8. -- 创建测试表 信息表
  9. CREATE TABLE mes(
  10. id INT ,
  11. content VARCHAR(30),
  12. send_time DATETIME);
  13. -- 添加一条记录
  14. INSERT INTO mes
  15. VALUES(1, '北京新闻', CURRENT_TIMESTAMP());
  16. INSERT INTO mes VALUES(2, '上海新闻', NOW());
  17. INSERT INTO mes VALUES(3, '广州新闻', NOW());
  18. SELECT * FROM mes;
  19. SELECT NOW() FROM DUAL;
  20. -- 上应用实例
  21. -- 显示所有新闻信息,发布日期只显示 日期,不用显示时间.
  22. SELECT id, content, DATE(send_time)
  23. FROM mes;
  24. -- 请查询在 10 分钟内发布的新闻, 思路一定要梳理一下.
  25. SELECT *
  26. FROM mes
  27. WHERE DATE_ADD(send_time, INTERVAL 10 MINUTE) >= NOW();
  28. SELECT *
  29. FROM mes
  30. WHERE send_time >= DATE_SUB(NOW(), INTERVAL 10 MINUTE);
  31. -- 请在 mysql sql 语句中求出 2011-11-11 1990-1-1 相差多少天
  32. SELECT DATEDIFF('2011-11-11', '1990-01-01') FROM DUAL;
  33. -- 请用 mysql sql 语句求出你活了多少天? [练习] 1986-11-11 出生
  34. SELECT DATEDIFF(NOW(), '1986-11-11') FROM DUAL;
  35. -- 如果你能活 80 岁,求出你还能活多少天.[练习] 1986-11-11 出生
  36. -- 先求出活 80 时, 是什么日期 X
  37. -- 然后在使用 datediff(x, now()); 1986-11-11->datetime
  38. -- INTERVAL 80 YEAR YEAR 可以是 年月日,时分秒
  39. -- '1986-11-11' 可以 date,datetime timestamp
  40. SELECT DATEDIFF(DATE_ADD('1986-11-11', INTERVAL 80 YEAR), NOW())
  41. FROM DUAL;
  42. SELECT TIMEDIFF('10:11:11', '06:10:10') FROM DUAL;
  43. -- YEAR|Month|DAY| DATE (datetime )
  44. SELECT YEAR(NOW()) FROM DUAL;
  45. SELECT MONTH(NOW()) FROM DUAL;
  46. SELECT DAY(NOW()) FROM DUAL;
  47. SELECT MONTH('2013-11-10') FROM DUAL;
  48. -- unix_timestamp() : 返回的是 1970-1-1 到现在的秒数
  49. SELECT UNIX_TIMESTAMP() FROM DUAL;
  50. -- FROM_UNIXTIME() : 可以把一个 unix_timestamp 秒数[时间戳],转成指定格式的日期
  51. -- %Y-%m-%d 格式是规定好的,表示年月日
  52. -- 意义:在开发中,可以存放一个整数,然后表示时间,通过 FROM_UNIXTIME 转换
  53. --
  54. SELECT FROM_UNIXTIME(1618483484, '%Y-%m-%d') FROM DUAL;
  55. SELECT FROM_UNIXTIME(1618483100, '%Y-%m-%d %H:%i:%s') FROM DUAL;
  56. SELECT * FROM mysql.user \G

十四、加密和系统函数

image.png

  1. -- 演示加密函数和系统函数
  2. -- USER() 查询用户
  3. -- 可以查看登录到 mysql 的有哪些用户,以及登录的 IP
  4. SELECT USER() FROM DUAL; -- 用户@IP 地址
  5. -- DATABASE()查询当前使用数据库名称
  6. SELECT DATABASE();
  7. -- MD5(str) 为字符串算出一个 MD5 32 的字符串,常用(用户密码)加密
  8. -- root 密码是 hsp -> 加密 md5 -> 在数据库中存放的是加密后的密码
  9. SELECT MD5('hsp') FROM DUAL;
  10. SELECT LENGTH(MD5('hsp')) FROM DUAL;
  11. -- 演示用户表,存放密码时,是 md5
  12. CREATE TABLE hsp_user
  13. (id INT ,
  14. `name` VARCHAR(32) NOT NULL DEFAULT '',
  15. pwd CHAR(32) NOT NULL DEFAULT '');
  16. INSERT INTO hsp_user
  17. VALUES(100, '韩顺平', MD5('hsp'));
  18. SELECT * FROM hsp_user; -- csdn
  19. SELECT * FROM hsp_user -- SQL 注入问题
  20. WHERE `name`='韩顺平' AND pwd = MD5('hsp')
  21. -- PASSWORD(str) -- 加密函数, MySQL 数据库的用户密码就是 PASSWORD 函数加密
  22. SELECT PASSWORD('hsp') FROM DUAL; -- 数据库的 *81220D972A52D4C51BB1C37518A2613706220DAC
  23. -- select * from mysql.user \G 从原文密码 str 计算并返回密码字符串
  24. -- 通常用于对 mysql 数据库的用户密码加密
  25. -- mysql.user 表示 数据库.表
  26. SELECT * FROM mysql.user

十五、流程控制函数

image.png

  1. # 演示流程控制语句
  2. # IF(expr1,expr2,expr3) 如果 expr1 为 True ,则返回 expr2 否则返回 expr3
  3. SELECT IF(TRUE, '北京', '上海') FROM DUAL;
  4. # IFNULL(expr1,expr2) 如果 expr1 不为空 NULL,则返回 expr1,否则返回 expr2
  5. SELECT IFNULL( NULL, '韩顺平教育') FROM DUAL;
  6. # SELECT CASE WHEN expr1 THEN expr2 WHEN expr3 THEN expr4 ELSE expr5 END; [类似多重分支.]
  7. # 如果 expr1 为 TRUE,则返回 expr2,如果 expr3 为 t, 返回 expr4, 否则返回 expr5
  8. SELECT CASE
  9. WHEN TRUE THEN 'jack' -- jack
  10. WHEN FALSE THEN 'tom'
  11. ELSE 'mary' END
  12. -- 1. 查询 emp 表, 如果 comm null , 则显示 0.0
  13. -- 老师说明,判断是否为 null 要使用 is null, 判断不为空 使用 is not
  14. SELECT ename, IF(comm IS NULL , 0.0, comm)
  15. FROM emp;
  16. SELECT ename, IFNULL(comm, 0.0)
  17. FROM emp;
  18. -- 2. 如果 emp 表的 job CLERK 则显示 职员, 如果是 MANAGER 则显示经理
  19. -- 如果是 SALESMAN 则显示 销售人员,其它正常显示
  20. SELECT ename, (SELECT CASE
  21. WHEN job = 'CLERK' THEN '职员'
  22. WHEN job = 'MANAGER' THEN '经理'
  23. WHEN job = 'SALESMAN' THEN '销售人员'
  24. ELSE job END) AS 'job'
  25. FROM emp;
  26. SELECT * FROM emp;
  27. SELECT * FROM dept;
  28. SELECT * FROM salgrade;

学习参考(致谢):

  1. B站 @程序员鱼皮 Java学习一条龙
  2. B站 @韩顺平 零基础30天学会Java