SQL中函数
🎯 本文专栏:MySQL深入浅出
🚀 作者主页:小度爱学习
SQL中函数
SQL中默认提供很多系统内置函数,帮助开发者实现各种需要的功能。
聚合函数
聚合函数对一组值进行运算,并返回单个值。也叫组合函数。
COUNT(*|列名) 统计行数
AVG(数值类型列名) 平均值
SUM (数值类型列名) 求和
MAX(列名) 最大值
MIN(列名) 最小值
除了COUNT()以外,聚合函数都会忽略NULL值。
函数名称 | 作用 |
---|---|
MAX | 查询指定列的最大值 |
MIN | 查询指定列的最小值 |
COUNT | 统计查询结果的行数 |
SUM | 求和,返回指定列的总和 |
AVG | 求平均值,返回指定列数据的平均值 |
面试题
count(*) 和 count(1)和count(列名)区别
count(1) and count(*)
当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count()用时多了!
从执行计划来看,count(1)和count()的效果是一样的。 但是在表做过分析之后,count(1)会比count(*)的用时少些(1w以内数据量),不过差不了多少。如果count(1)是聚索引,id,那肯定是count(1)快。但是差的很小的。
因为count(),自动会优化指定到那一个字段。所以没必要去count(1),用count(),sql会帮你完成优化的 因此:count(1)和count(*)基本没有差别!count(1) and count(字段)
两者的主要区别是
(1) count(1) 会统计表中的所有的记录数,包含字段为null 的记录。
(2) count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。count(*) 和 count(1)和count(列名)区别
执行效果上:
count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL
count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL
count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。执行效率上:
列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*)
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count(*)最优。
数值型函数
函数名称 | 作用 |
---|---|
ABS | 求绝对值 |
SQRT | 求平方根 |
POW 和 POWER | 两个函数的功能相同,返回参数的幂次方 |
MOD | 求余数 |
CEIL 和 CEILING | 两个函数功能相同,都是返回不小于参数的最小整数,即向上取整 |
FLOOR | 向下取整,返回值转化为一个BIGINT |
RAND | 生成一个0~1之间的随机数,传入整数参数是,用来产生重复序列 |
ROUND | 对所传参数进行四舍五入 |
SIGN | 返回参数的符号 |
字符串函数
函数名称 | 作用 |
---|---|
LENGTH | 计算字符串长度函数,返回字符串的字节长度 |
CHAR_LENGTH | 计算字符串长度函数,返回字符串的字符个数,注意两者的区别 |
CONCAT | 合并字符串函数,返回结果为连接参数产生的字符串,参数可以使一个或多个 |
INSERT(str,pos,len,newstr) | 替换字符串函数 |
LOWER | 将字符串中的字母转换为小写 |
UPPER | 将字符串中的字母转换为大写 |
LEFT(str,len) | 从左侧字截取符串,返回字符串左边的若干个字符 |
RIGHT | 从右侧字截取符串,返回字符串右边的若干个字符 |
TRIM | 删除字符串左右两侧的空格 |
REPLACE(s,s1,s2) | 字符串替换函数,返回替换后的新字符串 |
SUBSTRING(s,n,len) | 截取字符串,返回从指定位置开始的指定长度的字符换 |
REVERSE | 字符串反转(逆序)函数,返回与原始字符串顺序相反的字符串 |
STRCMP(expr1,expr2) | 比较两个表达式的顺序。若expr1 小于 expr2 ,则返回 -1,0相等,1则相反 |
LOCATE(substr,str [,pos]) | 返回第一次出现子串的位置 |
INSTR(str,substr) | 返回第一次出现子串的位置 |
日期和时间函数
函数名称 | 作用 |
---|---|
CURDATE() CURRENT_DATE() CURRENT_DATE | 两个函数作用相同,返回当前系统的日期值 |
CURTIME() CURRENT_TIME() CURRENT_TIME | 两个函数作用相同,返回当前系统的时间值 |
NOW | 返回当前系统的日期和时间值 |
SYSDATE | 返回当前系统的日期和时间值 |
DATE | 获取指定日期时间的日期部分 |
TIME | 获取指定日期时间的时间部分 |
MONTH | 获取指定日期中的月份 |
MONTHNAME | 获取指定曰期对应的月份的英文名称 |
DAYNAME | 获取指定曰期对应的星期几的英文名称 |
YEAR | 获取年份,返回值范围是 1970〜2069 |
DAYOFWEEK | 获取指定日期对应的一周的索引位置值,也就是星期数,注意周日是开始日,为1 |
WEEK | 获取指定日期是一年中的第几周,返回值的范围是否为 0〜52 或 1 〜53 |
DAYOFYEAR | 获取指定曰期是一年中的第几天,返回值范围是1~366 |
DAYOFMONTH 和 DAY | 两个函数作用相同,获取指定日期是一个月中是第几天,返回值范围是1~31 |
DATEDIFF(expr1,expr2) | 返回两个日期之间的相差天数,如 SELECT DATEDIFF(‘2007-12-31 23:59:59’,‘2007-12-30’); |
SEC_TO_TIME | 将秒数转换为时间,与TIME_TO_SEC 互为反函数 |
TIME_TO_SEC | 将时间参数转换为秒数,是指将传入的时间转换成距离当天00:00:00的秒数,00:00:00为基数,等于 0 秒 |
流程控制函数
函数名称 | 作用 |
---|---|
IF(expr,v1,v2) | 判断,流程控制,当expr = true时返回 v1,当expr = false、null 、 0时返回v2 |
IFNULL(v1,v2) | 判断是否为空,如果 v1 不为 NULL,则 IFNULL 函数返回 v1,否则返回 v2 |
CASE | 搜索语句 |
流程控制函数示例:
1、使用IF()函数进行条件判断
mysql> SELECT IF(12,2,3),-> IF(1<2,'yes ','no'),-> IF(STRCMP('test','test1'),'no','yes');
+------------+---------------------+---------------------------------------+
| IF(12,2,3) | IF(1<2,'yes ','no') | IF(STRCMP('test','test1'),'no','yes') |
+------------+---------------------+---------------------------------------+
| 2 | yes | no |
+------------+---------------------+---------------------------------------+
1 row in set (0.00 sec)2、分别显示emp表有奖金和没奖金的员工信息。
mysql> select ename,comm,if(comm is null,'没奖金,呵呵','有奖金,嘻嘻') 备注 from emp;
+-----------+-------+------------------+
| ename | comm | 备注 |
+-----------+-------+------------------+
| 甘宁 | NULL | 没奖金,呵呵 |
| 黛绮丝 | 3000 | 有奖金,嘻嘻 |
| 殷天正 | 5000 | 有奖金,嘻嘻 |
| 刘备 | NULL | 没奖金,呵呵 |
| 谢逊 | 14000 | 有奖金,嘻嘻 |
| 关羽 | NULL | 没奖金,呵呵 |
| 张飞 | NULL | 没奖金,呵呵 |
| 诸葛亮 | NULL | 没奖金,呵呵 |
| 曾阿牛 | NULL | 没奖金,呵呵 |
| 韦一笑 | 0 | 有奖金,嘻嘻 |
| 周泰 | NULL | 没奖金,呵呵 |
| 程普 | NULL | 没奖金,呵呵 |
| 庞统 | NULL | 没奖金,呵呵 |
| 黄盖 | NULL | 没奖金,呵呵 |
| 张三 | 50000 | 有奖金,嘻嘻 |
+-----------+-------+------------------+
15 rows in set (0.00 sec)3、使用IFNULL()函数进行条件判断
mysql> SELECT IFNULL(1,2), IFNULL(NULL,10), IFNULL(1/0, 'wrong');
+-------------+-----------------+----------------------+
| IFNULL(1,2) | IFNULL(NULL,10) | IFNULL(1/0, 'wrong') |
+-------------+-----------------+----------------------+
| 1 | 10 | wrong |
+-------------+-----------------+----------------------+
1 row in set, 1 warning (0.00 sec)
IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为
NULL 则返回第一个参数的值。
IFNULL() 函数语法格式为:
IFNULL(expression, alt_value)4、使用CASE value WHEN语句执行分支操作
CASE <表达式>WHEN <值1> THEN <操作>WHEN <值2> THEN <操作>...ELSE <操作>
END
将 <表达式> 的值 逐一和 每个 when 跟的 <值> 进行比较
如果跟某个<值>想等,则执行它后面的 <操作> ,如果所有 when 的值都不匹配,则执行 else 的操作
如果 when 的值都不匹配,且没写 else,则会报错
SELECT name,dept_id,
CASEdept_id WHEN 0 THEN"实习生" WHEN 1 THEN"销售部" WHEN 2 THEN"信息部" WHEN 2 THEN"财务部" ELSE "没有部门" END AS "部门"
FROMemp;mysql> SELECT CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;
+------------------------------------------------------------+
| CASE 2 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END |
+------------------------------------------------------------+
| two |
+------------------------------------------------------------+
1 row in set (0.00 sec)5、使用CASE WHEN语句执行分支操作
mysql> SELECT CASE WHEN 1<0 THEN 'true' ELSE 'false' END;
+--------------------------------------------+
| CASE WHEN 1<0 THEN 'true' ELSE 'false' END |
+--------------------------------------------+
| false |
+--------------------------------------------+
1 row in set (0.00 sec)6、查询emp表员工工资
要求:部门号为20,显示工资为1.2倍
部门号为30,显示工资为1.3倍
其他部门,显示原工资。
mysql> select deptno,sai 原工资,-> case deptno-> when 20 then sai*1.2-> when 30 then sai*1.3-> else sai-> end as 显示工资 from emp; +--------+-----------+--------------+
| deptno | 原工资 | 显示工资 |
+--------+-----------+--------------+
| 20 | 8000 | 9600.0 |
| 30 | 16000 | 20800.0 |
| 30 | 12500 | 16250.0 |
| 20 | 29750 | 35700.0 |
| 30 | 12500 | 16250.0 |
| 30 | 28500 | 37050.0 |
| 10 | 24500 | 24500 |
| 20 | 30000 | 36000.0 |
| 10 | 50000 | 50000 |
| 30 | 15000 | 19500.0 |
| 20 | 11000 | 13200.0 |
| 30 | 9500 | 12350.0 |
| 20 | 30000 | 36000.0 |
| 10 | 13000 | 13000 |
| 50 | 80000 | 80000 |
+--------+-----------+--------------+
15 rows in set (0.00 sec)7、查询员工工资情况
要求:工资大于20000,显示A
工资大于15000,显示B
工资大于10000,显示C
否则,显示D
mysql> select ename,sai,-> case-> when sai>20000 then 'A'-> when sai>15000 then 'B'-> when sai>10000 then 'C'-> else 'D'-> end as '工资级别' from emp;
+-----------+-------+--------------+
| ename | sai | 工资级别 |
+-----------+-------+--------------+
| 甘宁 | 8000 | D |
| 黛绮丝 | 16000 | B |
| 殷天正 | 12500 | C |
| 刘备 | 29750 | A |
| 谢逊 | 12500 | C |
| 关羽 | 28500 | A |
| 张飞 | 24500 | A |
| 诸葛亮 | 30000 | A |
| 曾阿牛 | 50000 | A |
| 韦一笑 | 15000 | C |
| 周泰 | 11000 | C |
| 程普 | 9500 | D |
| 庞统 | 30000 | A |
| 黄盖 | 13000 | C |
| 张三 | 80000 | A |
+-----------+-------+--------------+
15 rows in set (0.00 sec)