目录
5.3、CASE WHEN ... THEN ...WHEN ... THEN ... ELSE ... END
5.4、CASE ... WHEN ... THEN ... WHEN ... THEN ... ELSE ... END
1、Mysql的内置函数及分类
MySQL提供了丰富的内置函数,这些函数使得数据的维护与管理更加方便,能够更好地提供数据的分析与统计功能,在一定程度上提高了开发人员进行数据分析与统计的效率。
MySQL提供的内置函数从实现的功能角度可以分为数值函数、字符串函数、日期和时间函数、流程控制函数、加密与解密函数、获取MySQL信息函数、聚合函数等。这里,我将这些丰富的内置函数再分为两类:单行函数、聚合函数(分组函数)
单行函数
操作数据对象
接受参数返回一个结果
只对一行进行变换
每行返回一个结果
可以嵌套
参数可以是一列或一个值
2、数值函数
2.1、基本函数
#基本函数
SELECT ABS(-123),ABS(32),SIGN(-23),SIGN(43),PI(),CEIL(32.32),CEILING(-43.23),FLOOR(32.32),FLOOR(-43.23),MOD(12,5)
FROM DUAL;
SELECT RAND(),RAND(),RAND(10),RAND(10),RAND(-1),RAND(-1)
FROM DUAL;
#四舍五入,截断操作
SELECT ROUND(123.556),ROUND(123.456,0),ROUND(123.456,1),ROUND(123.456,2),ROUND(123.456,-1),ROUND(153.456,-2)
FROM DUAL;
SELECT TRUNCATE(123.456,0),TRUNCATE(123.496,1),TRUNCATE(129.45,-1)
FROM DUAL;
SELECT TRUNCATE(ROUND(123.456,2),0)
FROM DUAL;
2.2、角度与弧度互换函数
1弧度约等于57.3度
#角度与弧度的互换
SELECT RADIANS(30),RADIANS(60),RADIANS(90),DEGREES(2*PI()),DEGREES(RADIANS(90))
FROM DUAL;
2.3、三角函数
ATAN2(M,N)函数返回两个参数的反正切值。 与ATAN(X)函数相比,ATAN2(M,N)需要两个参数,例如有两个点point(x1,y1)和point(x2,y2),使用ATAN(X)函数计算反正切值为ATAN((y2-y1)/(x2-x1)),使用ATAN2(M,N)计算反正切值则为ATAN2(y2-y1,x2-x1)。由使用方式可以看出,当x2-x1等于0时,ATAN(X)函数会报错,而ATAN2(M,N)函数则仍然可以计算。
#三角函数
SELECT SIN(RADIANS(30)),DEGREES(ASIN(1)),TAN(RADIANS(45)),DEGREES(ATAN(1)),DEGREES(ATAN2(1,0))
FROM DUAL;
2.4、指数与对数
注意:LOG(x, y) 返回以x为底y的对数, 如LOG(2, 8)返回3
#指数和对数
SELECT POW(2,5),POWER(2,4),EXP(2), LN(EXP(2)),LOG(EXP(2)),LOG10(10),LOG2(4),LOG(2,8)
FROM DUAL;
2.5、进制间的转换
#进制间的转换
SELECT BIN(10),HEX(10),OCT(10),CONV(10,10,8)
FROM DUAL;
3、字符串函数
注意:MySQL中,字符串的位置是从1开始的。
3.1、CHAR_LENGTH 和 LENGTH 的区别
SELECT ASCII('Abcdfsf'),CHAR_LENGTH('hello'),CHAR_LENGTH('我们'),LENGTH('hello'),LENGTH('我们')
FROM DUAL;
3.2、CONCAT 和 CONCAT_WS的区别
# xxx worked for yyy
SELECT CONCAT(emp.last_name,' worked for ',mgr.last_name) "details"
FROM employees emp JOIN employees mgr
WHERE emp.`manager_id` = mgr.employee_id;
SELECT CONCAT_WS('-','hello','world','hello','beijing')
FROM DUAL;
3.3、INSERT 和 REPLACE
注意:若REPLACE中不存在要替换的字符串,会返回原字符串,不会报错
#字符串的索引是从1开始的!
SELECT INSERT('helloworld',2,3,'aaaaa'),REPLACE('hello','llo','mmm')
FROM DUAL;
3.4、LPAD 和 RPAD
# LPAD:实现右对齐效果
# RPAD:实现左对齐效果
SELECT LPAD(salary,10,' ') '左对齐', RPAD(salary,10,' ') '右对齐'
FROM employees;
4、日期和时间函数
4.1、获取日期、时间
#3.1 获取日期、时间
SELECT CURDATE(),CURRENT_DATE(),CURTIME(),NOW(),SYSDATE(),UTC_DATE(),UTC_TIME()
FROM DUAL;
SELECT CURDATE(),CURDATE() + 0,CURTIME(),CURTIME() + 0,NOW() + 0
FROM DUAL;
4.2、日期和时间戳的转换
#3.2 日期与时间戳的转换
SELECT UNIX_TIMESTAMP(),UNIX_TIMESTAMP('2021-10-01 12:12:32'),FROM_UNIXTIME(1635173853),FROM_UNIXTIME(1633061552)
FROM DUAL;
4.3、获取月份、星期、星期数、天数等函数
SELECT YEAR(CURDATE()),MONTH(CURDATE()),DAY(CURDATE()),HOUR(CURTIME()),MINUTE(NOW()),SECOND(SYSDATE())
FROM DUAL;
SELECT MONTHNAME(CURDATE()),DAYNAME(CURDATE()),WEEKDAY(CURDATE()),
QUARTER(CURDATE()),WEEK(CURDATE()),DAYOFYEAR(NOW()),
DAYOFMONTH(NOW()),DAYOFWEEK(NOW())
FROM DUAL;
4.4、日期的操作函数
EXTRACT(type FROM date)函数中type的取值与含义:
#3.4 日期的操作函数
SELECT EXTRACT(SECOND FROM NOW()),EXTRACT(DAY FROM NOW()),
EXTRACT(HOUR_MINUTE FROM NOW()),EXTRACT(QUARTER FROM '2021-05-12')
FROM DUAL;
4.5、时间和秒钟转换的函数
#3.5 时间和秒钟转换的函数
SELECT TIME_TO_SEC(CURTIME()), SEC_TO_TIME(77668)
FROM DUAL;
4.6、计算日期和时间的函数
第一组:
上述函数中type的取值:
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY) AS col1,DATE_ADD('2021-10-21 23:32:12',INTERVAL 1 SECOND) AS col2,
ADDDATE('2021-10-21 23:32:12',INTERVAL 1 SECOND) AS col3,
DATE_ADD('2021-10-21 23:32:12',INTERVAL '1_1' MINUTE_SECOND) AS col4,
DATE_ADD(NOW(), INTERVAL -1 YEAR) AS col5, #可以是负数
DATE_ADD(NOW(), INTERVAL '1_1' YEAR_MONTH) AS col6 #需要单引号
FROM DUAL;
第二组:
注意:
PERIOD_ADD(time,n)增加N个月至时间time(格式为YYMM或YYYYMM)。返回格式为YYYYMM的值。注意:time不是日期值。
SELECT ADDTIME(NOW(),20),SUBTIME(NOW(),30),SUBTIME(NOW(),'1:1:3'),DATEDIFF(NOW(),'2021-10-01'),
TIMEDIFF(NOW(),'2021-10-25 22:10:10'),FROM_DAYS(366)
FROM DUAL;
SELECT TO_DAYS('0000-12-25'),LAST_DAY(NOW()),MAKEDATE(YEAR(NOW()),12),MAKETIME(10,21,23),PERIOD_ADD(9802,2)
FROM DUAL;
4.7、日期的格式化与解析
上述非GET_FORMAT
函数中fmt参数常用的格式符:
GET_FORMAT函数中date_type和format_type参数取值如下:
#格式化:
SELECT DATE_FORMAT(CURDATE(),'%Y-%M-%D'),
DATE_FORMAT(NOW(),'%Y-%m-%d'),TIME_FORMAT(CURTIME(),'%h:%i:%S'),
DATE_FORMAT(NOW(),'%Y-%M-%D %h:%i:%S %W %w %T %r')
FROM DUAL;
#解析:格式化的逆过程
SELECT STR_TO_DATE('2021-October-25th 11:37:30 Monday 1','%Y-%M-%D %h:%i:%S %W %w')
FROM DUAL;
SELECT GET_FORMAT(DATE,'USA')
FROM DUAL;
SELECT DATE_FORMAT(CURDATE(),GET_FORMAT(DATE,'USA'))
FROM DUAL;
5、流程控制函数
流程处理函数可以根据不同的条件,执行不同的处理流程,可以在SQL语句中实现不同的条件选择。MySQL中的流程处理函数主要包括IF()、IFNULL()和CASE()函数。
5.1、IF(VALUE,VALUE1,VALUE2)
SELECT last_name,salary,IF(salary >= 6000,'高工资','低工资') "details"
FROM employees;
SELECT last_name,commission_pct,IF(commission_pct IS NOT NULL,commission_pct,0) "details",
salary * 12 * (1 + IF(commission_pct IS NOT NULL,commission_pct,0)) "annual_sal"
FROM employees;
5.2、IFNULL(VALUE1,VALUE2)
#4.2 IFNULL(VALUE1,VALUE2):看做是IF(VALUE,VALUE1,VALUE2)的特殊情况
SELECT last_name,commission_pct,IFNULL(commission_pct,0) "details"
FROM employees;
5.3、CASE WHEN ... THEN ...WHEN ... THEN ... ELSE ... END
#4.3 CASE WHEN ... THEN ...WHEN ... THEN ... ELSE ... END
# 类似于java的if ... else if ... else if ... else
SELECT last_name,salary,CASE WHEN salary >= 15000 THEN '社会精英'
WHEN salary >= 10000 THEN '潜力股'
WHEN salary >= 5000 THEN '屌丝男士'
ELSE '小草根' END "details",department_id
FROM employees;
5.4、CASE ... WHEN ... THEN ... WHEN ... THEN ... ELSE ... END
SELECT employee_id, last_name, department_id, salary, CASE department_id WHEN 10 THEN salary * 1.1
WHEN 20 THEN salary * 1.2
WHEN 30 THEN salary * 1.3
ELSE salary * 1.4 END 'detail'
FROM employees
WHERE department_id IN(10,20,30);
6、加密与解密函数
加密与解密函数主要用于对数据库中的数据进行加密和解密处理,以防止数据被他人窃取。这些函数在保证数据库安全时非常有用。
可以看到,ENCODE(value,password_seed)函数与DECODE(value,password_seed)函数互为反函数。
#ENCODE()\DECODE() 在mysql8.0中弃用。
SELECT ENCODE('mysql','mysql'),DECODE(ENCODE('mysql','mysql'),'mysql')
FROM DUAL;
7、MySQL信息函数
MySQL中内置了一些可以查询MySQL信息的函数,这些函数主要用于帮助数据库开发或运维人员更好地对数据库进行维护工作。
#6. MySQL信息函数
SELECT VERSION(),CONNECTION_ID(),DATABASE(),SCHEMA(),
USER(),CURRENT_USER(),CHARSET('哈哈哈'),COLLATION('哈哈哈')
FROM DUAL;
8、其他函数
MySQL中有些函数无法对其进行具体的分类,但是这些函数在MySQL的开发和运维过程中也是不容忽视的。
注意:
FORMAT(value,n) 如果n的值小于或者等于0,则只保留整数部分
INET_ATON(ipvalue)转换方式:以“192.168.1.100”为例,计算方式为192乘以256的3次方,加上168乘以256的2次方,加上1乘以256,再加上100。
#如果n的值小于或者等于0,则只保留整数部分
SELECT FORMAT(123.125,2),FORMAT(123.125,0),FORMAT(123.125,-2)
FROM DUAL;
#以“192.168.1.100”为例,计算方式为192乘以256的3次方,加上168乘以256的2次方,加上1乘以256,再加上100。
SELECT INET_ATON('192.168.1.100'),INET_NTOA(3232235876)
FROM DUAL;
# CONVERT():可以实现字符集的转换
SELECT CHARSET('atguigu'),CHARSET(CONVERT('atguigu' USING 'gbk'))
FROM DUAL;
9、练习
# 1.显示系统时间(注:日期+时间)
SELECT NOW(),SYSDATE(),CURRENT_TIMESTAMP(),LOCALTIME(),LOCALTIMESTAMP()
FROM DUAL;
# 2.查询员工号,姓名,工资,以及工资提高百分之20%后的结果(new salary)
SELECT employee_id, last_name, salary, IF(salary, salary, 0) * 1.2 'new salary'
FROM employees
# 3.将员工的姓名按首字母排序,并写出姓名的长度(length)
SELECT last_name, LENGTH(last_name) "name_length"
FROM employees
ORDER BY last_name;
# 4.查询员工id,last_name,salary,并作为一个列输出,别名为OUT_PUT
SELECT CONCAT_WS('-', employee_id, last_name, salary) "OUT_PUT"
FROM employees;
# 5.查询公司各员工工作的年数、工作的天数,并按工作年数的降序排序
SELECT employee_id, ROUND(DATEDIFF(NOW(),hire_date)/365) "worked_years", DATEDIFF(NOW(),hire_date) "worked_days",
TO_DAYS(NOW()) - TO_DAYS(hire_date) "worked_days1"
FROM employees
ORDER BY worked_years DESC;
# 6.查询员工姓名,hire_date , department_id,满足以下条件:
# 雇用时间在1997年之后,department_id 为80 或 90 或110, commission_pct不为空
SELECT employee_id, hire_date, department_id
FROM employees
WHERE department_id IN(80,90,100)
AND commission_pct IS NOT NULL
# 雇用时间在1997年之后可以采用以下条件之一
#and datediff(hire_date, '1997-01-01') >= 0;
#and hire_date >= '1997-01-01' #存在隐式转换
#and date_format(hire_date, '%Y-%m-%d') >= '1997-01-01' # 显式转换操作,格式化:日期---> 字符串
#and DATE_FORMAT(hire_date, '%Y') >= '1997' # 显式转换操作,格式化
AND hire_date >= STR_TO_DATE('1997-01-01', '%Y-%m-%d') #显式转换操作,解析:字符串 ----> 日期
# 7.查询公司中入职超过10000天的员工姓名、入职时间
SELECT last_name, hire_date
FROM employees
WHERE DATEDIFF(NOW(), hire_date) > 10000;
# 8.做一个查询,产生下面的结果 <last_name> earns <salary> monthly but wants <salary*3>
SELECT CONCAT(last_name,' earns ',TRUNCATE(salary,0),' monthly but wants ',TRUNCATE(salary * 3,0)) 'Dream Salary'
FROM employees;
# 9.使用case-when,按照下面的条件输出last_name, job_id, grade
#job grade
#AD_PRES A
#ST_MAN B
#IT_PROG C
#SA_REP D
#ST_CLERK E
#其他 F
SELECT last_name, job_id, CASE job_id WHEN 'AD_PRES' THEN 'A'
WHEN 'ST_MAN' THEN 'B'
WHEN 'IT_PROG' THEN 'C'
WHEN 'SA_REP' THEN 'D'
WHEN 'ST_CLERK' THEN 'E'
ELSE 'F'
END 'grade'
FROM employees