阅读整理自《MySQL 必知必会》- 朱晓峰,详细内容请登录 极客时间 官网购买专栏。
数学函数
主要用来处理数值数据,常用的主要有 3 类,分别是取整函数 ROUND()、CEIL()、FLOOR(),绝对值函数 ABS() 和求余函数 MOD()。
数据准备:
demo.transactiondetail
mysql> select transactionid, itemnumber, quantity, price, discount, salesvalue
-> from demo.transactiondetails
-> order by transactionid, itemnumber;
+---------------+------------+----------+-------+----------+------------+
| transactionid | itemnumber | quantity | price | discount | salesvalue |
+---------------+------------+----------+-------+----------+------------+
| 1 | 1 | 2 | 89.00 | 0.99 | 176.22 |
| 1 | 2 | 5 | 5.00 | 0.99 | 24.75 |
| 2 | 1 | 3 | 89.00 | 0.88 | 234.96 |
| 2 | 2 | 6 | 5.00 | 0.88 | 26.40 |
| 3 | 1 | 1 | 89.00 | 0.95 | 84.55 |
| 3 | 2 | 10 | 5.00 | 0.95 | 47.50 |
+---------------+------------+----------+-------+----------+------------+
demo.transacionhead
mysql> select transactionid, transactionno, cashierid, memberid, operatorid, transdate
-> from demo.transactionhead;
+---------------+------------------+-----------+----------+------------+---------------------+
| transactionid | transactionno | cashierid | memberid | operatorid | transdate |
+---------------+------------------+-----------+----------+------------+---------------------+
| 1 | 0120201201000001 | 1 | 1 | 1 | 2020-12-01 00:00:00 |
| 2 | 0120201202000001 | 1 | 2 | 2 | 2020-12-02 00:00:00 |
| 3 | 0120201202000002 | 1 | NULL | 1 | 2020-12-01 01:00:00 |
+---------------+------------------+-----------+----------+------------+---------------------+
demo.goodsmaster
mysql> select * from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-----------+
| itemnumber | barcode | goodsname | specification | unit | saleprice |
+------------+---------+-----------+---------------+------+-----------+
| 1 | 0001 | 书 | | 本 | 89.00 |
| 2 | 0002 | 笔 | | 支 | 5.00 |
+------------+---------+-----------+---------------+------+-----------+
demo.membermaster
mysql> select memberid, branchid, cardno, membername, address, phone, pid, memeberpoints, memberdeposit from demo.membermaster;
+----------+----------+----------+------------+---------+-------------+--------------------+---------------+---------------+
| memberid | branchid | cardno | membername | address | phone | pid | memeberpoints | memberdeposit |
+----------+----------+----------+------------+---------+-------------+--------------------+---------------+---------------+
| 1 | 1 | 10000001 | 张三 | 天津 | 13698765432 | 475145197001012356 | 0.00 | 0.00 |
| 2 | 1 | 10000002 | 李四 | 上海 | 18758079161 | 123123199001012356 | 0.00 | 0.00 |
+----------+----------+----------+------------+---------+-------------+--------------------+---------------+---------------+
取整函数
- 向上取整 ceil(X) 和 ceiling(X):返回大于等于 X 的最小 INT 型整数
- 向下取整 floor(X):返回小于等于 X 的最大 INT 型整数
- 舍入函数 round(X,D):X 表示要处理的数,D 表示保留的小数位数,处理的方式是四舍五入,ROUND(X) 表示保留 0 位小数
需求:积分的规则是一元积一分,不满一元不积分,显然是向下取整,那就可以用 FLOOR()函数。
通过关联查询,获得会员消费的相关信息:
mysql> select c.membername as '会员',
-> b.transactionno as '单号',
-> b.transdate as '时间',
-> d.goodsname as '商品名称',
-> a.salesvalue as '交易金额'
-> from demo.transactiondetails a
-> join demo.transactionhead b on (b.transactionid = a.transactionid)
-> join demo.membermaster c on (c.memberid = b.memberid)
-> join demo.goodsmaster d on (d.itemnumber = a.itemnumber);
+------+------------------+---------------------+----------+----------+
| 会员 | 单号 | 时间 | 商品名称 | 交易金额 |
+------+------------------+---------------------+----------+----------+
| 张三 | 0120201201000001 | 2020-12-01 00:00:00 | 书 | 176.22 |
| 张三 | 0120201201000001 | 2020-12-01 00:00:00 | 笔 | 24.75 |
| 李四 | 0120201202000001 | 2020-12-02 00:00:00 | 书 | 234.96 |
| 李四 | 0120201202000001 | 2020-12-02 00:00:00 | 笔 | 26.40 |
+------+------------------+---------------------+----------+----------+
用 floor(a.salesvalue)
,对销售金额向下取整,获取会员积分值
select c.membername as '会员',
b.transactionno as '单号',
b.transdate as '时间',
d.goodsname as '商品名称',
floor(a.salesvalue) as '积分'
from demo.transactiondetails a
join demo.transactionhead b on (b.transactionid = a.transactionid)
join demo.membermaster c on (c.memberid = b.memberid)
join demo.goodsmaster d on (d.itemnumber = a.itemnumber);
+------+------------------+---------------------+----------+------+
| 会员 | 单号 | 时间 | 商品名称 | 积分 |
+------+------------------+---------------------+----------+------+
| 张三 | 0120201201000001 | 2020-12-01 00:00:00 | 书 | 176 |
| 张三 | 0120201201000001 | 2020-12-01 00:00:00 | 笔 | 24 |
| 李四 | 0120201202000001 | 2020-12-02 00:00:00 | 书 | 234 |
| 李四 | 0120201202000001 | 2020-12-02 00:00:00 | 笔 | 26 |
+------+------------------+---------------------+----------+------+
或者:
mysql> select 1.5 - mod(1.5, 1);
+-------------------+
| 1.5 - mod(1.5, 1) |
+-------------------+
| 1.0 |
+-------------------+
mysql> select 1.1 - mod(1.1, 1);
+-------------------+
| 1.1 - mod(1.1, 1) |
+-------------------+
| 1.0 |
+-------------------+
需求:收银的时候,应收金额可以被设定四舍五入到哪一位。比如,可以设定四舍五入到元、到角,或者到分。
mysql> select round(salesvalue, 2)
-> from demo.transactiondetails where transactionid=1 and itemnumber=1;
+----------------------+
| round(salesvalue, 2) |
+----------------------+
| 176.22 |
+----------------------+
mysql> select round(salesvalue, 1)
-> from demo.transactiondetails where transactionid=1 and itemnumber=1;
+----------------------+
| round(salesvalue, 1) |
+----------------------+
| 176.2 |
+----------------------+
mysql> select round(salesvalue)
-> from demo.transactiondetails where transactionid=1 and itemnumber=1;
+-------------------+
| round(salesvalue) |
+-------------------+
| 176 |
+-------------------+
字符串函数
常用的字符串函数有 4 个。
- concat(s1,s2,…):表示把字符串 s1、s2…… 拼接起来,组成一个字符串
- cast(表达式 as char):表示将表达式的值转换成字符串
- char_length(字符串):表示获取字符串的长度
- space(n):表示获取一个由 n 个空格组成的字符串
需求:完成交易之后,系统必须要打出一张小票。打印小票时,对格式有很多要求。比如说,一张小票纸,57 毫米宽,大概可以打 32 个字符,也就是 16 个汉字。用户要求一条流水打 2 行,第一行是商品信息,第二行要包括数量、价格、折扣和金额 4 种信息。那么,怎么才能清晰地在小票上打印出这些信息,并且打印得整齐漂亮呢?
-
打印第一行的商品信息。商品信息包括:商品名称和商品规格,而且商品规格要包含在括号里面。这样就必须把商品名称和商品规格拼接起来,变成一个字符串。
mysql> select concat(goodsname, '(', specification, ')') as 商品信息 -> from demo.goodsmaster where itemnumber=1; +----------+ | 商品信息 | +----------+ | 书(16开) | +----------+
-
如何打印第二行。第二行包括数量、价格、折扣和金额,一共是 4 种信息。
转为字符串
mysql> select cast(quantity as char) -- 把数量转换成字符串,把decimal类型转换成字符串 -> from demo.transactiondetails -> where transactionid=1 and itemnumber=1; +------------------------+ | cast(quantity as char) | +------------------------+ | 2 | +------------------------+
计算字符串的长度
mysql> select char_length(cast(quantity as char)) as 长度 -> from demo.transactiondetails where transactionid=1 and itemnumber=1; +------+ | 长度 | +------+ | 1 | +------+
空格补齐 7 位长度
mysql> select concat(cast(quantity as char), space(7-char_length(cast(quantity as char)))) as 数量 -> from demo.transactiondetails where transactionid=1 and itemnumber=1; +---------+ | 数量 | +---------+ | 2 | +---------+
字符串函数:https://dev.mysql.com/doc/refman/8.0/en/string-functions.html
条件判断函数
条件判断函数的主要作用,就是根据特定的条件返回不同的值,常用的有两种:
ifnull(V1, V2)
:表示如果 V1 的值不为空值,则返回 V1,否则返回 V2if(表达式, V1, V2)
:如果表达式为真(TRUE),则返回 V1,否则返回 V2
mysql> select goodsname, specification, concat(goodsname, '(', ifnull(specification, ''), ')') as 拼接
-> from demo.goodsmaster;
+-----------+---------------+----------+
| goodsname | specification | 拼接 |
+-----------+---------------+----------+
| 书 | 16开 | 书(16开) |
| 笔 | NULL | 笔() |
+-----------+---------------+----------+
mysql> select goodsname, specification, if(isnull(specification), goodsname, concat(goodsname, '(', ifnull(specification, ''), ')')) as 拼接
-> from demo.goodsmaster;
+-----------+---------------+----------+
| goodsname | specification | 拼接 |
+-----------+---------------+----------+
| 书 | 16开 | 书(16开) |
| 笔 | NULL | 笔 | -- 去掉多余的()
+-----------+---------------+----------+
小结
函数 | 功能 |
---|---|
数学计算函数 | floor(x): 获取小于等于x的最大整数 |
ceil(x): 获取大于等于x的最小整数 | |
round(x, d): 通过四舍五入,获得最接近x的,保留d位小数的数值 | |
abs(): 获取x的绝对值 | |
mod(x, y): 获取x被y整除后的余数 | |
concat(s1,s2,…): 连接字符串s1,s2,… | |
char_length(s): 获取字符串s中的字符的个数,一个汉字算一个字符 | |
字符串函数 | space(n): 获取由n个空格组成的字符串 |
substr() 和 mid(): 获取字符串中的子字符串 | |
trim(): 删除字符串开头两端的子字符串 | |
ltrim(): 删除字符串开头部分的空格 | |
rtrim(): 删除字符串结尾部分的空格 | |
条件判断函数 | ifnull(v1, v2): 如果v1为空,返回v2,否则返回v1 |
if(表达式, v1, v2): 如果表达式为真,返回v1,否则返回v2 |
函数也有一些坑,比如 round(x) 对x四舍五入后不一定比原来的x大:
mysql> select round(-1.5);
+-------------+
| round(-1.5) |
+-------------+
| -2 |
+-------------+
mysql> select round(-1.5, 0);
+----------------+
| round(-1.5, 0) |
+----------------+
| -2 |
+----------------+
mysql> select round(-1.5, 1);
+----------------+
| round(-1.5, 1) |
+----------------+
| -1.5 |
+----------------+