MySQL数据库学习笔记2--系统函数(分组,单行,窗口函数)

六.运算符

6.1 算术运算符(掌握)

mysql 复制代码
加:+
	在MySQL +就是求和,没有字符串拼接
减:-
乘:*
除:/   div(只保留整数部分)
	div:两个数相除只保留整数部分
	/:数学中的除
模:%   mod

mysql中没有 +=等运算符
mysql 复制代码
#select 表达式
select 1+1;
update t_employee set salary = salary+100 where eid=27;

select 9/2, 9 div 2;

mysql> select 9/2, 9 div 2;
+--------+---------+
| 9/2    | 9 div 2 |
+--------+---------+
| 4.5000 |       4 |
+--------+---------+
1 row in set (0.00 sec)
mysql 复制代码
select 9.5 / 1.5 , 9.5 div 1.5;

mysql> select 9.5 / 1.5 , 9.5 div 1.5;
+-----------+-------------+
| 9.5 / 1.5 | 9.5 div 1.5 |
+-----------+-------------+
|   6.33333 |           6 |
+-----------+-------------+
1 row in set (0.00 sec)

select 9 % 2, 9 mod 2;
select 9.5 % 1.5 , 9.5 mod 1.5;
mysql 复制代码
select 'hello' + 'world';
mysql> select 'hello' + 'world';
+-------------------+
| 'hello' + 'world' |
+-------------------+
|                 0 |
+-------------------+
1 row in set, 2 warnings (0.00 sec)

6.2 比较运算符(掌握)

复制代码
大于:>
小于:<
大于等于:>=
小于等于:<=
等于:=   不能用于null判断
不等于:!=  或 <>  不能用于null判断
算数 10 / 4  2.5 
        div -- 没有余数 10 div 4  -- 2
处理null值:
    是null:
	字段 is null
	字段 <=> null
    
    不是null:
	字段 is not null
	not 字段 <=> null 
逻辑
   and or xor not
   
区间集合
   [not]between X and Y [X,Y]
   [not] in (值....)   	
模糊匹配:
   like
      %:任意多个
      _:任意一个  	

查询薪资高于15000的员工姓名和薪资

sql 复制代码
select ename,salary from t_employee where salary>15000;

mysql> select ename,salary from t_employee where salary>15000;
+--------+--------+
| ename  | salary |
+--------+--------+
| 孙洪亮 |  28000 |
| 贾宝玉 |  15700 |
| 黄冰茹 |  15678 |
| 李冰冰 |  18760 |
| 谢吉娜 |  18978 |
| 舒淇格 |  16788 |
| 章嘉怡 |  15099 |
+--------+--------+
7 rows in set (0.00 sec)

查询薪资正好是9000的员工姓名和薪资

sql 复制代码
select ename,salary from t_employee where salary = 9000;
select ename,salary from t_employee where salary == 9000;#错误,不支持==  #注意Java中判断用==,mysql判断用=

mysql> select ename,salary from t_employee where salary == 9000;
ERROR 1064 (42000): You have an error in your SQL syntax;
 check the manual that corresponds to your MySQL server version for the right syntax to use near '== 9000' at line 1

查询籍贯native_place不是北京的

sql 复制代码
select * from t_employee where native_place != '北京';
select * from t_employee where native_place <> '北京';

查询员工表中部门编号不是1

sql 复制代码
select * from t_employee where did != 1;
select * from t_employee where did <> 1;

查询奖金比例是NULL

sql 复制代码
select * from t_employee where commission_pct = null; 

mysql> select * from t_employee where commission_pct = null; #无法用=null判断
Empty set (0.00 sec)

查询奖金比例是NULL

sql 复制代码
select * from t_employee where commission_pct <=> null; 
select * from t_employee where commission_pct is null; 

查询"李冰冰"、"周旭飞"、"李易峰"这几个员工的信息

sql 复制代码
select * from t_employee where ename in ('李冰冰','周旭飞','李易峰');

查询部门编号为2、3的员工信息

sql 复制代码
select * from t_employee where did in(2,3);

查询部门编号不是2、3的员工信息

sql 复制代码
select * from t_employee where did not in(2,3);

查询薪资在10000,15000之间

sql 复制代码
select * from t_employee where salary between 10000 and 15000;

查询姓名中第二个字是'冰'的员工

sql 复制代码
select * from t_employee where ename like '冰'; #这么写等价于 ename='冰'
select * from t_employee where ename like '_冰%'; 
#这么写匹配的是第二个字是冰,后面可能没有第三个字,或者有好几个字

update t_employee set ename = '王冰' where ename = '李冰冰';

select * from t_employee where ename like '_冰_'; 
#这么写匹配的是第二个字是冰,后面有第三个字,且只有三个字

查询员工的姓名、薪资、奖金比例、实发工资

sql 复制代码
#实发工资 = 薪资 + 薪资 * 奖金比例
select ename as 姓名,
salary as 薪资,
commission_pct as 奖金比例,
salary + salary * commission_pct as 实发工资
from t_employee;

NULL在mysql中比较和计算都有特殊性,所有的计算遇到的null都是null。

sql 复制代码
#实发工资 = 薪资 + 薪资 * 奖金比例
select ename as 姓名,
salary as 薪资,
commission_pct as 奖金比例,
salary + salary * ifnull(commission_pct,0) as 实发工资
from t_employee;

6.3 区间或集合范围比较运算符(掌握)

复制代码
区间范围:between x  and  y  [x,y]
    not between x  and  y
集合范围:in (x,x,x)
    not  in(x,x,x)

#查询薪资在10000,15000

sql 复制代码
select * from t_employee where salary>=10000 && salary<=15000;
select * from t_employee where salary between 10000 and 15000;

#查询籍贯在这几个地方的

sql 复制代码
select * from t_employee where native_place in ('北京', '浙江', '江西');

#查询薪资不在10000,15000

sql 复制代码
select * from t_employee where salary not between 10000 and 15000;

#查询籍贯不在这几个地方的

sql 复制代码
select * from t_employee where native_place not in ('北京', '浙江', '江西');

6.4 模糊匹配比较运算符(掌握)

复制代码
%:代表任意个字符

_:代表一个字符,如果两个下划线代表两个字符

#查询名字中包含'冰'字

sql 复制代码
select * from t_employee where ename like '%冰%';

#查询名字以'雷'结尾的

sql 复制代码
select * from t_employee where ename like '%雷';

#查询名字以'李'开头

sql 复制代码
select * from t_employee where ename like '李%';

#查询名字有冰这个字,但是冰的前面只能有1个字

sql 复制代码
select * from t_employee where ename like '_冰%';

6.5 逻辑运算符(掌握)

复制代码
逻辑与:&& 或 and
逻辑或:|| 或 or
逻辑非:! 或 not
逻辑异或: xor

#查询薪资高于15000,并且性别是男的员工

sql 复制代码
select * from t_employee where salary>15000 and gender='男';
select * from t_employee where salary>15000 && gender='男';

select * from t_employee where salary>15000 & gender='男';#错误 &按位与
select * from t_employee where (salary>15000) & (gender='男');

#查询薪资高于15000,或者did为1的员工

sql 复制代码
select  * from t_employee where salary>15000 or did = 1;
select  * from t_employee where salary>15000 || did = 1;

#查询薪资不在15000,20000范围的

sql 复制代码
select  * from t_employee where salary not between 15000 and 20000;
select  * from t_employee where !(salary between 15000 and 20000);

#查询薪资高于15000,或者did为1的员工,两者只能满足其一

sql 复制代码
select  * from t_employee where salary>15000 xor did = 1;
select  * from t_employee where (salary>15000) ^ (did = 1);

6.6 关于null值的问题(掌握)

复制代码
#(1)判断时
xx is null
xx is not null
xx <=> null

#(2)计算时
ifnull(xx,代替值)  当xx是null时,用代替值计算

#查询奖金比例为null的员工

sql 复制代码
select * from t_employee where commission_pct = null;  #失败
select * from t_employee where commission_pct = NULL; #失败
select * from t_employee where commission_pct = 'NULL'; #失败

select * from t_employee where commission_pct is null;   #成功
select * from t_employee where commission_pct <=> null;  #成功  <=>安全等于

#查询员工的实发工资,实发工资 = 薪资 + 薪资 * 奖金比例

sql 复制代码
select ename , salary + salary * commission_pct "实发工资" from t_employee; #失败,当commission_pct为null,结果都为null

select ename ,salary , commission_pct, salary + salary * ifnull(commission_pct,0) "实发工资" from t_employee;

6.7 位运算符(了解)

mysql 复制代码
左移:<<
右移:>>
按位与:&
按位或:|
按位异或:^
按位取反:~

七. 系统预定义函数

函数:代表一个独立的可复用的功能。

和python中的方法有所不同,不同点在于:MySQL中的函数必须有返回值,参数可以有,可以没有。

MySQL中函数分为:

(1)系统预定义函数:MySQL数据库管理软件给我提供好的函数,直接用就可以,任何数据库都可以用公共的函数。

  • 分组函数:或者又称为聚合函数,多行函数,表示会对表中的多行记录一起做一个"运算",得到一个结果。
    • 求平均值的avg,求最大值的max,求最小值的min,求总和sum,求个数的count等
  • 单行函数:表示会对表中的每一行记录分别计算,有n行得到还是n行结果
    • 数学函数、字符串函数、日期时间函数、条件判断函数、窗口函数等

(2)用户自定义函数:由开发人员自己定义的,通过CREATE FUNCTION语句定义,是属于某个数据库的对象。

7.1 分组函数

调用完函数后,结果的行数变少了,可能得到一行,可能得到少数几行。

分组函数有合并计算过程。

常用分组函数类型

  • AVG(x) :求平均值

  • SUM(x):求总和

  • MAX(x) :求最大值

  • MIN(x) :求最小值

  • **COUNT(x) **:统计记录数

演示分组函数,聚合函数,多行函数

#统计t_employee表的员工的数量

sql 复制代码
SELECT COUNT(*) FROM t_employee;
SELECT COUNT(1) FROM t_employee;
SELECT COUNT(eid) FROM t_employee;
SELECT COUNT(commission_pct) FROM t_employee;

/*
count(*)或count(常量值):都是统计实际的行数。
count(字段/表达式):只统计"字段/表达式"部分非NULL值的行数。
*/

#找出t_employee表中最高的薪资值

sql 复制代码
SELECT MAX(salary) FROM t_employee;

#找出t_employee表中最低的薪资值

sql 复制代码
SELECT MIN(salary) FROM t_employee;

#统计t_employee表中平均薪资值

sql 复制代码
SELECT AVG(salary) FROM t_employee;

#统计所有人的薪资总和,财务想看一下,一个月要准备多少钱发工资

sql 复制代码
SELECT SUM(salary) FROM t_employee; #没有考虑奖金
SELECT SUM(salary+salary*IFNULL(commission_pct,0)) FROM t_employee; 

#找出年龄最小、最大的员工的出生日期

sql 复制代码
SELECT MAX(birthday),MIN(birthday) FROM t_employee;

#查询最新入职的员工的入职日期

sql 复制代码
SELECT MAX(hiredate) FROM t_employee;

7.2 单行函数

调用完函数后,记录数不变,一行计算完之后还是一行。

1、数学函数

以下表格中也只是列出了一部分

函数 用法
ABS(x) 返回x的绝对值
CEIL(x) 返回大于x的最小整数值
FLOOR(x) 返回小于x的最大整数值
MOD(x,y) 返回x/y的模
RAND() 返回0~1的随机值
ROUND(x,y) 返回参数x的四舍五入的有y位的小数的值
TRUNCATE(x,y) 返回数字x截断为y位小数的结果
FORMAT(x,y) 强制保留小数点后y位,整数部分超过三位的时候以逗号分割,并且返回的结果是文本类型的
SQRT(x) 返回x的平方根
POW(x,y) 返回x的y次方

单行函数,演示数学函数

#在"t_employee"表中查询员工无故旷工一天扣多少钱,

#分别用CEIL、FLOOR、ROUND、TRUNCATE函数。

sql 复制代码
#假设本月工作日总天数是22天,
#旷工一天扣的钱=salary/22。
SELECT ename,salary/22,CEIL(salary/22),
FLOOR(salary/22),ROUND(salary/22,2),
TRUNCATE(salary/22,2) FROM t_employee; 

#查询公司平均薪资,并对平均薪资分别

#使用CEIL、FLOOR、ROUND、TRUNCATE函数

sql 复制代码
SELECT AVG(salary),CEIL(AVG(salary)),
FLOOR(AVG(salary)),ROUND(AVG(salary)),
TRUNCATE(AVG(salary),2) FROM t_employee;

2、字符串函数

下面列出部分字符串函数:

函数 功能描述
CONCAT(S1,S2,......Sn) 连接S1,S2,......Sn为一个字符串
CONCAT_WS(s,S1,S2,......Sn) 同CONCAT(S1,S2,...)函数,但每个字符串之间要加上s
CHAR_LENGTH(s) 返回字符串s的字符数
LENGTH(s) 返回字符串s的字节数,和字符集有关
LOCATE(str1,str)或 POSITION(str1 in str)或 INSTR(str,str1) 返回子字符串str1在str中的开始位置
UPPER(s)或UCASE(s) 将字符串s的所有字母转成大写字母
LOWER(s)或LCASE(s) 将字符串s的所有字母转成小写字母
LEFT(s,n) 返回字符串s最左边的n个字符
RIGHT(s,n) 返回字符串s最右边的n个字符
LPAD(str,len,pad) 用字符串pad对str最左边进行填充直到str的长度达到len
RPAD(str,len,pad) 用字符串pad对str最右边进行填充直到str的长度达到len
LTRIM(s) 去掉字符串s左侧的空格
RTRIM(s) 去掉字符串s右侧的空格
TRIM(s) 去掉字符串s开始与结尾的空格
TRIM(BOTH s1 FROM s) 去掉字符串s开始与结尾的s1
TRIM(LEADING s1 FROM s) 去掉字符串s开始处的s1
TRIM(TRAILINGs1 FROM s) 去掉字符串s结尾处的s1
INSERT(str,index,len,instr) 将字符串str从index位置开始len个字符的替换为字符串instr
REPLACE(str,a,b) 用字符串b替换字符串str中所有出现的字符串a
REPEAT(str,n) 返回str重复n次的结果
REVERSE(s) 将字符串反转
STRCMP(s1,s2) 比较字符串s1,s2
SUBSTRING(s,index,len) 返回从字符串s的index位置截取len个字符
SUBSTRING_INDEX(str, 分隔符,count) 如果count是正数,那么从左往右数,第n个分隔符的左边的全部内容。例如,substring_index("www.atguigu.com",".",1)是"www"。如果count是负数,那么从右边开始数,第n个分隔符右边的所有内容。例如,substring_index("www.atguigu.com",".",-1)是"com"。

字符串函数

复制代码
mysql中不支持 + 拼接字符串,需要调用函数来拼接
(1)在"t_employee"表中查询员工姓名ename和电话tel,
并使用CONCAT函数,CONCAT_WS函数。
sql 复制代码
SELECT CONCAT(ename,tel),CONCAT_WS('-',ename,tel) FROM t_employee;
复制代码
(2)在"t_employee"表中查询薪资高于15000的男员工姓名,
sql 复制代码
#并把姓名处理成"张xx"的样式。
#LEFT(s,n)函数表示取字符串s最左边的n个字符,
#而RPAD(s,len,p)函数表示在字符串s的右边填充p使得字符串长度达到len。
SELECT  RPAD(LEFT(ename,1),3,'x'),salary
FROM t_employee
WHERE salary>15000 AND gender ='男';
复制代码
(3)在"t_employee"表中查询薪资高于10000的男员工姓名、
sql 复制代码
#姓名包含的字符数和占用的字节数。
SELECT ename,CHAR_LENGTH(ename) AS 占用字符数,LENGTH(ename) AS 占用字节数量
FROM t_employee
WHERE salary>10000 AND gender ='男'

;

复制代码
(4)在"t_employee"表中查询薪资高于10000的男员工姓名和邮箱email,
并把邮箱名"@"字符之前的字符串截取出来。
sql 复制代码
SELECT ename,email,
SUBSTRING(email,1, POSITION('@' IN email)-1)
FROM t_employee
WHERE salary > 10000 AND gender ='男';
复制代码
mysql中 SUBSTRING截取字符串位置,下标从1开始,不是和Java一样从0开始。
mysql中 position等指定字符串中某个字符,子串的位置也不是从0开始,都是从1开始。
sql 复制代码
SELECT TRIM('    hello   world   '); #默认是去掉前后空白符
SELECT CONCAT('[',TRIM('    hello   world   '),']'); #默认是去掉前后空白符
SELECT TRIM(BOTH '&' FROM '&&&&hello   world&&&&'); #去掉前后的&符号
SELECT TRIM(LEADING '&' FROM '&&&&hello   world&&&&'); #去掉开头的&符号
SELECT TRIM(TRAILING '&' FROM '&&&&hello   world&&&&'); #去掉结尾的&符号

3、日期时间函数

函数 功能描述
CURDATE()或CURRENT_DATE() 返回当前系统日期
CURTIME()或CURRENT_TIME() 返回当前系统时间
NOW()/SYSDATE()/CURRENT_TIMESTAMP()/ LOCALTIME()/LOCALTIMESTAMP() 返回当前系统日期时间
UTC_DATE()/UTC_TIME() 返回当前UTC日期值/时间值UTC(协调世界时)是全球统一时间的标准。它是基于原子钟生成的时间,被认为是"最精确的时间"。
UNIX_TIMESTAMP(date) 返回一个UNIX时间戳
YEAR(date)/MONTH(date)/DAY(date)/ HOUR(time)/MINUTE(time)/SECOND(time) 返回具体的时间值
EXTRACT(type FROM date) 从日期中提取一部分值
DAYOFMONTH(date)/DAYOFYEAR(date) 返回一月/年中第几天
WEEK(date)/WEEKOFYEAR(date) 返回一年中的第几周
DAYOFWEEK() 返回周几,注意,周日是1,周一是2,...周六是7
WEEKDAY(date) 返回周几,注意,周一是0,周二是1,...周日是6
DAYNAME(date) 返回星期,MONDAY,TUESDAY,...SUNDAY
MONTHNAME(date) 返回月份,January,...
DATEDIFF(date1,date2)/TIMEDIFF(time1,time2) 返回date1-date2的日期间隔/返回time1-time2的时间间隔
DATE_ADD(date,INTERVAL expr type)或ADDDATE/DATE_SUB/SUBDATE 返回与给定日期相差INTERVAL时间段的日期
ADDTIME(time,expr)/SUBTIME(time,expr) 返回给定时间加上/减去expr的时间值
DATE_FORMAT(datetime,fmt)/ TIME_FORMAT(time,fmt) 按照字符串fmt格式化日期datetime值/时间time值
STR_TO_DATE(str,fmt) 按照字符串fmt对str进行解析,解析为一个日期
GET_FORMAT(val_type,format_type) 返回日期时间字符串的显示格式

函数中日期时间类型说明

参数类型 描述 参数类型 描述
YEAR YEAR_MONTH 年月
MONTH DAY_HOUR 日时
DAY DAY_MINUTE 日时分
HOUR DAY_SECOND 日时分秒
MINUTE HOUR_MINUTE 时分
SECOND HOUR_SECOND 时分秒
WEEK 星期 MINUTE_SECOND 分秒
QUARTER 季度信息

函数中format参数说明

格式符 说明 格式符 说明
%Y 4位数字表示年份 %y 两位数字表示年份
%M 月名表示月份(January,...) %m 两位数字表示月份(01,02,03,...)
%b 缩写的月名(Jan.,Feb.,...) %c 数字表示月份(1,2,3...)
%D 英文后缀表示月中的天数(1st,2nd,3rd,...) %d 两位数字表示表示月中的天数(01,02,...)
%e 数字形式表示月中的天数(1,2,3,...) %p AM或PM
%H 两位数字表示小数,24小时制(01,02,03,...) %h和%I 两位数字表示小时,12小时制(01,02,03,...)
%k 数字形式的小时,24小时制(1,2,3,...) %l 数字表示小时,12小时制(1,2,3,...)
%i 两位数字表示分钟(00,01,02,...) %S和%s 两位数字表示秒(00,01,02,...)
%T 时间,24小时制(hh:mm:ss) %r 时间,12小时制(hh:mm:ss)后加AM或PM
%W 一周中的星期名称(Sunday,...) %a 一周中的星期缩写(Sun.,Mon.,Tues.,...)
%w 以数字表示周中的天数(0=Sunday,1=Monday,...) %j 以3位数字表示年中的天数(001,002,...)
%U 以数字表示的的第几周(1,2,3,...) 其中Sunday为周中的第一天 %u 以数字表示年中的年份(1,2,3,...) 其中Monday为周中第一天
%V 一年中第几周(01~53),周日为每周的第一天,和%X同时使用 %X 4位数形式表示该周的年份,周日为每周第一天,和%V同时使用
%v 一年中第几周(01~53),周一为每周的第一天,和%x同时使用 %x 4位数形式表示该周的年份,周一为每周第一天,和%v同时使用
%% 表示%

GET_FORMAT函数中val_type 和format_type参数说明

值类型 格式化类型 显示格式字符串
DATE EUR %d.%m.%Y
DATE INTERVAL %Y%m%d
DATE ISO %Y-%m-%d
DATE JIS %Y-%m-%d
DATE USA %m.%d.%Y
TIME EUR %H.%i.%s
TIME INTERVAL %H%i%s
TIME ISO %H:%i:%s
TIME JIS %H:%i:%s
TIME USA %h:%i:%s %p
DATETIME EUR %Y-%m-%d %H.%i.%s
DATETIME INTERVAL %Y%m%d %H%i%s
DATETIME ISO %Y-%m-%d %H:%i:%s
DATETIME JIS %Y-%m-%d %H:%i:%s
DATETIME USA %Y-%m-%d %H.%i.%s

日期时间函数

复制代码
获取系统日期时间值
获取某个日期或时间中的具体的年、月等值
获取星期、月份值,可以是当天的星期、当月的月份
获取一年中的第几个星期,一年的第几天
计算两个日期时间的间隔
获取一个日期或时间间隔一定时间后的另个日期或时间
和字符串之间的转换

复制代码
(1)获取系统日期。
CURDATE()和CURRENT_DATE()函数都可以获取当前系统日期。将日期值"+0"会怎么样?
sql 复制代码
SELECT CURDATE(),CURRENT_DATE();
复制代码
(2)获取系统时间。
CURTIME()和CURRENT_TIME()函数都可以获取当前系统时间。将时间值"+0"会怎么样?
sql 复制代码
SELECT CURTIME(),CURRENT_TIME();
复制代码
(3)获取系统日期时间值。
CURRENT_TIMESTAMP()、LOCALTIME()、SYSDATE()和NOW()
sql 复制代码
SELECT CURRENT_TIMESTAMP(),LOCALTIME(),SYSDATE(),NOW();
复制代码
(4)获取当前UTC(世界标准时间)日期或时间值。
本地时间是根据地球上不同时区所处的位置调整 UTC 得来的,
例如,北京时间比UTC时间晚8个小时。
sql 复制代码
#UTC_DATE(),CURDATE(),UTC_TIME(), CURTIME()
SELECT UTC_DATE(),CURDATE(),UTC_TIME(), CURTIME();
复制代码
(5)获取UNIX时间戳。
sql 复制代码
SELECT UNIX_TIMESTAMP(),UNIX_TIMESTAMP('2022-1-1');
复制代码
(6)获取具体的时间值,比如年、月、日、时、分、秒。
分别是YEAR(date)、MONTH(date)、DAY(date)、HOUR(time)、MINUTE(time)、SECOND(time)。
sql 复制代码
SELECT YEAR(CURDATE()),MONTH(CURDATE()),DAY(CURDATE());
SELECT HOUR(CURTIME()),MINUTE(CURTIME()),SECOND(CURTIME());
复制代码
(7)获取日期时间的指定值。
EXTRACT(type FROM date/time)函数
sql 复制代码
SELECT EXTRACT(YEAR_MONTH FROM CURDATE());
复制代码
(8)获取两个日期或时间之间的间隔。
sql 复制代码
#DATEDIFF(date1,date2)函数表示返回两个日期之间间隔的天数。
#TIMEDIFF(time1,time2)函数表示返回两个时间之间间隔的时分秒

#查询今天距离员工入职的日期间隔天数
SELECT ename,DATEDIFF(CURDATE(),hiredate) FROM t_employee;

#查询现在距离中午放学还有多少时间
SELECT TIMEDIFF(CURTIME(),'12:0:0');
复制代码
(9)在"t_employee"表中查询本月生日的员工姓名、生日。
sql 复制代码
SELECT ename,birthday
FROM t_employee
WHERE MONTH(CURDATE()) = MONTH(birthday);
复制代码
(10)#查询入职时间超过5年的
sql 复制代码
SELECT ename,hiredate,DATEDIFF(CURDATE(),hiredate) 
FROM t_employee
WHERE DATEDIFF(CURDATE(),hiredate)  > 365*5;

SELECT STR_TO_DATE('1992-01-01',"%Y-%m-%d");

4、加密函数

列出了部分的加密函数。

函数 用法
password(str) 返回字符串str的加密版本,41位长的字符串(mysql8不再支持)
md5(str) 返回字符串str的md5值,也是一种加密方式(Message-Digest Algorithm 5,信息摘要算法第五版)
SHA(str) 返回字符串str的sha算法加密字符串,40位十六进制值的密码字符串 (Secure Hash Algorithm)
SHA2(str,hash_length) 返回字符串str的sha算法加密字符串,密码字符串的长度是hash_length/4。hash_length可以是224、256、384、512、0,其中0等同于256。

加密函数

复制代码
当用户需要对数据进行加密时,
比如做登录功能时,给用户的密码加密等。
mysql 复制代码
#password函数在mysql8已经移除了
SELECT PASSWORD('123456');

#使用md5加密
SELECT MD5('123456'),SHA('123456'),sha2('123456',0);

SELECT CHAR_LENGTH(MD5('123456')),SHA('123456'),sha2('123456',0);


CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
PASSWORD VARCHAR(100)
);

INSERT INTO t_user VALUES(NULL,'chai',MD5('123456'));

SELECT * FROM t_user 
WHERE username='chai' AND PASSWORD =MD5('123456');


SELECT * FROM t_user 
WHERE username='chai' AND PASSWORD ='123456';

5、系统信息函数

函数 用法
database() 返回当前数据库名
version() 返回当前数据库版本
user() 返回当前登录用户名
mysql 复制代码
#其他函数
SELECT USER();
SELECT VERSION();
SELECT DATABASE();

6、条件判断函数

复制代码
   if(X,Y,Z): X:真  Y
                假  Z   
   ifnull(v1,v2): v1不为null 返回v1 否则返回v2
   
   类似与(if elif else) case when 条件 then 结果 
		....
		[else 值] end 
   类似于(match case) case 表达式 when 常量值 then 结果 
                ....
		[else 值] end
函数 功能
IF(value,t,f) 如果value是真,返回t,否则返回f
IFNULL(value1,value2) 如果value1不为空,返回value1,否则返回value2
CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2 ... ELSE resultn END 依次判断条件,哪个条件满足了,就返回对应的result,所有条件都不满足就返回ELSE的result。如果没有单独的ELSE子句,当所有WHEN后面的条件都不满足时则返回NULL值结果。等价于pythn中if...elif... else.
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值2 THEN 值2 ... ELSE 值n END 判断表达式expr与哪个常量值匹配,找到匹配的就返回对应值,都不匹配就返回ELSE的值。如果没有单独的ELSE子句,当所有WHEN后面的常量值都不匹配时则返回NULL值结果。等价于Java中switch...case
mysql 复制代码
#条件判断函数
/*
这个函数不是筛选记录的函数,
而是根据条件不同显示不同的结果的函数。
*/
#如果薪资大于20000,显示高薪,否则显示正常
SELECT ename,salary,IF(salary>20000,'高薪','正常')
FROM t_employee;

#计算实发工资
#实发工资 = 薪资 + 薪资 * 奖金比例
SELECT ename,salary,commission_pct,
salary + salary * commission_pct
FROM t_employee;
#如果commission_pct是,计算完结果是NULL

SELECT ename,salary,commission_pct,
salary + salary * IFNULL(commission_pct,0) AS 实发工资
FROM t_employee;


SELECT ename,salary,commission_pct,
ROUND(salary + salary * IFNULL(commission_pct,0),2) AS 实发工资
FROM t_employee;

#查询员工编号,姓名,薪资,等级,等级根据薪资判断,
#如果薪资大于20000,显示"羡慕级别",
#如果薪资15000-20000,显示"努力级别",
#如果薪资10000-15000,显示"平均级别"
#如果薪资10000以下,显示"保底级别"
/*mysql中没有if...elseif函数,有case 函数。
等价于if...elseif 
*/
SELECT eid,ename,salary,
CASE WHEN salary>20000 THEN '羡慕级别'
     WHEN salary>15000 THEN '努力级别'
     WHEN salary>10000 THEN '平均级别'
     ELSE '保底级别'
END AS "等级"
FROM t_employee;  

#在"t_employee"表中查询入职7年以上的
#员工姓名、工作地点、轮岗的工作地点数量情况。
/*
计算工作地点的数量,转换为求 work_place中逗号的数量+1。
 work_place中逗号的数量 = work_place的总字符数 -  work_place去掉,的字符数
 work_place去掉, ,使用replace函数
*/
SELECT work_place, 
CHAR_LENGTH(work_place)-CHAR_LENGTH(REPLACE(work_place,',',''))
FROM t_employee;
 
 #类似于Java中switch...case
SELECT ename,work_place,
CASE (CHAR_LENGTH(work_place)-CHAR_LENGTH(REPLACE(work_place,',',''))+1)
WHEN 1 THEN '只在一个地方工作'
WHEN 2 THEN '在两个地方来回奔波'
WHEN 3 THEN '在三个地方流动'
ELSE '频繁出差'
END AS "工作地点数量情况"
FROM t_employee
WHERE DATEDIFF(CURDATE(),hiredate)  > 365*7;

7、其他函数

从5.7.8版本之后开始支持JSON数据类型,并提供了操作JSON类型的数据的相关函数。

MySQL提供了非常丰富的空间函数以支持各种空间数据的查询和处理。

这两类函数基础阶段不讲,如果项目中有用到查询API使用。

7.3 窗口函数

复制代码
函数名([参数列表]) OVER ()
	函数名([参数列表]) OVER (子句)
	函数名(参数列表) over(
	  [partition by column]
	  [order by column]
	  [rows between <start> and <end>]
	)

	序号函数:
	   row_number(): 每一条记录添加编号
	   rank(): 并列排序 会跳过
	   dense_rank():并列排序 不会跳过
	其他:
	   lag() 上n个 lead() 下n个
	   first_value() 第一个
	   last_value()  最后一个  ORDER BY salary ROWS BETWEEN unbounded preceding AND  unbounded following 整张表
	   
	注意:
	   1.over()没有写子句 则将整个结果集看成是一个窗口

窗口函数也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据进行实时分析处理。窗口函数是每条记录都会分析,有几条记录执行完还是几条,因此也属于单行函数。

窗口函数 说明
row_number() 顺序排序,每行按照不同的分组逐行编号,例如:1,2,3,4
rank() 并列排序,每行按照不同的分组进行编号,同一个分组中排序字段值出现重复值时,并列排序并跳过重复序号,例如:1,1,3
dense_rank() 并列稠密排序,每行按照不同的分组进行编号,同一个分组中排序字段值出现重复值时,并列排序不跳过重复序号,例如:1,1,2
lag()/lead() 访问窗口中当前行前/后一定偏移量的值
first_value()/last_value() 访问窗口中第一个或最后一个值

窗口函数的语法格式如下

mysql 复制代码
函数名([参数列表]) OVER ()
函数名([参数列表]) OVER (子句)
函数名(参数列表) over(
  [partition by column]
  [order by column]
  [rows between <start> and <end>]
)

over关键字用来指定窗口函数的窗口范围。如果OVER后面是空(),则表示SELECT语句筛选的所有行是一个窗口。OVER后面的()中支持以下3种语法来设置窗口范围。

  • window:给窗口指定一个别名

  • partition by:一个窗口范围还可以分为多个区域。按照哪些字段进行分区/分组,窗口函数在不同的分组上分别处理分析

  • order by:按照哪些字段进行排序,窗口函数将按照排序后结果进行分析处理

  • rows/range between and :在计算窗口函数时,指定哪些行/值将被包含在计算范围内,和用于定义窗口范围:

Ø unbounded preceding:窗口从分区的第一行开始

Ø n preceding:当前行之前的n行

Ø current row:当前行

Ø n following: 当前行之后的n行

Ø unbounded following:窗口到分区的最后一行

mysql 复制代码
use atguigu;
-- 在t_employee表中查询薪资在[8000,10000]之间的员工姓名和薪资并给每一行记录编序号
select row_number() over() as rn,ename,salary
from t_employee
where salary between 8000 and 10000;
-- 计算每一个部门的平均薪资与全公司的平均薪资的差值
select distinct
  did,
  avg(salary) over(partition by did),
  avg(salary) over(),
  round(avg(salary) over(partition by did)-avg(salary) over(),2) as deviation
from t_employee;
-- 在t_employee表中查询女员工姓名,部门编号,薪资
-- 查询结果按照部门编号分组后在按薪资升序排列
-- 并分别使用row_number()、rank()、dense_rank()三个序号函数给每一行记录编序号
select ename,did,salary,gender,
row_number() over(partition by did order by salary) as "row_num",
rank() over(partition by did order by salary) as "rank_num",
dense_rank() over(partition by did order by salary) as "ds_rank_num"
from t_employee where gender='女';
-- 或使用window给窗口指定别名
select ename,did,salary,
row_number() over w as "row_num",
rank() over w as "rank_num" ,
dense_rank() over w as "ds_rank_num" 
from t_employee where gender='女'
window w as(partition by did order by salary);
-- 在t_employee表中查询每个部门最低3个薪资值的女员工姓名,部门编号,薪资值
select row_number() over() as rn,temp.*
from(select ename,did,salary,
row_number() over w as "row_num",
rank() over w as "rank_num" ,
dense_rank() over w as "ds_rank_num"
from t_employee where gender='女'
window w as(partition by did order by salary))temp
where temp.rank_num<=3;
-- 在t_employee表中查询每个部门薪资排名前3的员工姓名,部门编号,薪资值
select temp.*
from(select ename,did,salary,
dense_rank() over w as "ds_rank_num"
from t_employee
window w as(partition by did order by salary desc))temp
where temp.ds_rank_num<=3;
-- 在t_employee表中查询全公司薪资排名前3的员工姓名,部门编号,薪资值
select temp.*
from(select ename,did,salary,
dense_rank() over w as "ds_rank_num"
from t_employee
window w as(order by salary desc))temp
where temp.ds_rank_num<=3;
-- 查找薪资排名的上一位、下一位、首位、末位
select
  ename,
  salary,
  lag(ename,1,'-') over(order by salary) as '上一位姓名',
  lag(salary,1,0) over(order by salary) as '上一位薪资',
  lead(ename) over(order by salary) as '下一位姓名',
  lead(salary) over(order by salary) as '下一位薪资',
  first_value(salary) over(order by salary) as '首位薪资',
  last_value(ename) over(order by salary rows between unbounded preceding and unbounded following) as '末位姓名'
from t_employee;
相关推荐
dadaobusi1 小时前
学习:XS-Gem5参数
学习
我不是程序员三三2 小时前
如何监控电脑|企业终端行为监控概念科普与落地方法论
数据库·电脑·php
大牧师2 小时前
TypeORM 入门教程
后端·sql·mysql·orm·nest·typeorm
LearnYard2 小时前
技术博主实测:2026年大语言模型辅助学习工具横向对比
人工智能·学习·语言模型
oliver_sys_log2 小时前
绕过 Yearning 查询体验限制:我做了一个 DataGrip 只读 SQL 代理
后端·mysql
M78佐菲3 小时前
HTML学习笔记
linux·笔记·学习·tcp/ip·html
lhldsg3 小时前
全民健身解决方案软件开发实战:从架构设计到部署指南
java·前端·数据库·小程序
我是大猴子3 小时前
线上耗时问题排查
数据库
小码过河.3 小时前
oceanbase中zone和observer、分区表之间关系
前端·数据库·oceanbase