乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

数值函数

导学

数值函数让你在 SQL 中直接完成数学运算,无需将数据拉回程序层。本节梳理 MySQL 5.7 中最常用的数值函数,包括取整、随机、幂运算和进制转换。

定义

数值函数:对数值型数据进行数学运算并返回结果的函数。MySQL 5.7 提供算术运算、取整、随机、三角函数、对数、进制转换等数十个数值函数。

常用数值函数

取整函数

ROUND、CEIL、FLOOR、TRUNCATE

当前数据状态:

以下用常量演示取整函数的效果:

SELECT
    3.14159 AS value,
    ROUND(3.14159, 2) AS round_2,
    ROUND(3.14159) AS round_int,
    CEIL(3.14159) AS ceil_val,
    FLOOR(3.14159) AS floor_val,
    TRUNCATE(3.14159, 2) AS truncate_2
UNION ALL
SELECT
    -2.71828,
    ROUND(-2.71828, 2),
    ROUND(-2.71828),
    CEIL(-2.71828),
    FLOOR(-2.71828),
    TRUNCATE(-2.71828, 2);

操作后的数据状态:

valueround_2round_intceil_valfloor_valtruncate_2
3.141593.143433.14
-2.71828-2.72-3-2-3-2.71

结果解读:

  • ROUND(value, 2):四舍五入到 2 位小数,3.14159 变为 3.14
  • ROUND(value):四舍五入到整数,采用"四舍六入五成双"规则
  • CEIL(value):向上取整,3.14159 变为 4
  • FLOOR(value):向下取整,3.14159 变为 3
  • TRUNCATE(value, 2):直接截断到 2 位小数,不进行四舍五入,3.14159 变为 3.14

Banker's Rounding 演示

SELECT
    ROUND(2.5) AS round_2_5,
    ROUND(3.5) AS round_3_5,
    ROUND(4.5) AS round_4_5;

结果:

round_2_5round_3_5round_4_5
244

结果解读:MySQL 的 ROUND 采用"四舍六入五成双"(Banker's Rounding):当舍弃部分恰好为 0.5 时,向最近的偶数舍入。ROUND(2.5) = 2(2 是偶数),ROUND(3.5) = 4(4 是偶数)。

随机函数

RAND

当前数据状态:

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前表数据:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

操作语句:

-- 生成 0 ~ 1 之间的随机浮点数
SELECT RAND() AS random_float;

-- 生成 0 ~ 99 之间的随机整数
SELECT FLOOR(RAND() * 100) AS random_int_0_99;

-- 随机抽取 1 条记录
SELECT * FROM employees ORDER BY RAND() LIMIT 1;

操作后的数据状态(随机结果每次不同,以下为示例):

随机抽取结果示例:

emp_idemp_namedeptscore
1大翔技术部100

结果解读:

  • RAND() 生成 [0, 1) 范围内的随机浮点数
  • FLOOR(RAND() * 100) 生成 0 ~ 99 的随机整数
  • ORDER BY RAND() LIMIT 1 随机排序后取前 1 条

性能警告:ORDER BY RAND() 需要为每行生成随机数并全排序,大数据量时极慢。替代方案:在程序层生成随机 ID 后用 WHERE id IN (...) 查询。

绝对值与符号

当前数据状态:

以下用常量演示绝对值和符号函数:

SELECT
    100.00 AS amount,
    ABS(100.00) AS abs_amount,
    SIGN(100.00) AS sign_val
UNION ALL
SELECT
    -50.50,
    ABS(-50.50),
    SIGN(-50.50);

操作后的数据状态:

amountabs_amountsign_val
100.00100.001
-50.5050.50-1

结果解读:

  • ABS(amount) 返回绝对值,负数转为正数
  • SIGN(amount) 返回符号:正数为 1,负数为 -1,零为 0

幂与根

当前数据状态:

以下用常量演示幂与根函数:

SELECT
    2.00 AS base,
    10 AS exponent,
    POW(2.00, 10) AS power_result,
    SQRT(2.00) AS sqrt_result,
    LOG(2.00) AS natural_log,
    LOG10(2.00) AS log10_result
UNION ALL
SELECT
    16.00,
    0,
    POW(16.00, 0),
    SQRT(16.00),
    LOG(16.00),
    LOG10(16.00);

操作后的数据状态:

baseexponentpower_resultsqrt_resultnatural_loglog10_result
2.00101024.001.41420.69310.3010
16.0001.004.00002.77261.2041

结果解读:

  • POW(2, 10) = 1024,即 2 的 10 次方
  • SQRT(16) = 4,16 的平方根
  • LOG(10) 是自然对数(以 e 为底),约 2.3026
  • LOG10(10) 是以 10 为底的对数,结果为 1

进制转换

当前数据状态:

以下用常量演示进制转换函数:

SELECT
    10 AS decimal_val,
    BIN(10) AS binary_str,
    HEX(10) AS hex_str,
    CONV(HEX(10), 16, 10) AS back_to_dec
UNION ALL
SELECT
    255,
    BIN(255),
    HEX(255),
    CONV(HEX(255), 16, 10);

操作后的数据状态:

decimal_valbinary_strhex_strback_to_dec
101010A10
25511111111FF255

结果解读:

  • BIN(10) 将十进制 10 转为二进制字符串 '1010'
  • HEX(255) 将十进制 255 转为十六进制字符串 'FF'
  • CONV('FF', 16, 10) 将十六进制转为十进制,返回 '255'(字符串形式)

SQL 综合示例

场景一:金额四舍五入

当前数据状态:

以下用常量演示金额四舍五入:

SELECT
    199.9950 AS total_amount,
    ROUND(199.9950, 2) AS round_2,
    ROUND(199.9950 * 0.95, 2) AS discounted_amount
UNION ALL
SELECT
    88.8888,
    ROUND(88.8888, 2),
    ROUND(88.8888 * 0.95, 2);

操作后的数据状态:

total_amountround_2discounted_amount
199.9950200.00190.00
88.888888.8984.44

结果解读:订单金额保留两位小数展示,同时计算 95 折优惠后的金额。注意 199.9950 四舍五入到两位小数时变为 200.00。

场景二:分页随机推荐

当前数据状态:复用上面的 employees 表。

低性能写法(大数据量禁用):

SELECT * FROM employees ORDER BY RAND() LIMIT 1;

结果示例:

emp_idemp_namedeptscore
1大翔技术部100

高性能替代方案(需有自增主键):

SELECT s.* FROM employees s
JOIN (
    SELECT emp_id FROM employees
    ORDER BY RAND() LIMIT 1
) tmp ON s.emp_id = tmp.emp_id;

结果解读:第一种写法对整个表排序,时间复杂度 O(N log N)。第二种写法先对较小的主键列随机排序取 ID,再通过 JOIN 取完整数据,减少了排序的数据量。但大数据量下仍建议程序层生成随机 ID 再查询。

场景三:生成指定范围随机整数

-- 生成 10 ~ 20 之间的随机整数
SELECT FLOOR(10 + RAND() * 11) AS random_10_to_20;

结果示例:

random_10_to_20
15

结果解读:公式为 FLOOR(min + RAND() * (max - min + 1))。RAND() 生成 [0, 1),乘以 11 得 [0, 11),加 10 得 [10, 21),FLOOR 后得到 10 ~ 20 的整数。

常见误区

误区正解
ROUND 和 TRUNCATE 一样ROUND 四舍五入,TRUNCATE 直接截断。TRUNCATE(3.99, 0) = 3,ROUND(3.99) = 4。
RAND() 可以生成唯一随机数RAND() 可能重复,不能作为唯一标识。
CEIL 和 FLOOR 只是别称CEIL(3.1) = 4,FLOOR(3.9) = 3,方向相反。

面试考点

Q:ROUND(2.5) 和 ROUND(3.5) 的结果?

MySQL 的 ROUND 采用"四舍六入五成双"(Banker's Rounding):ROUND(2.5) = 2,ROUND(3.5) = 4。与通常的"四舍五入"不同。

Q:如何生成指定范围内的随机整数?

FLOOR(min + RAND() * (max - min + 1))。例如 10~20 之间的随机整数:FLOOR(10 + RAND() * 11)。

Q:ORDER BY RAND() 为什么慢?如何优化?

需要为每行生成随机数并全排序,时间复杂度 O(N log N)。优化方案:1. 程序层生成随机 ID 列表再查询;2. 用范围随机 WHERE id > RAND() * MAX_ID LIMIT 1(不均匀但快);3. 额外维护一个随机排序字段。

小结

  • ROUND 四舍五入,TRUNCATE 直接截断
  • CEIL 向上取整,FLOOR 向下取整
  • RAND() 用于随机数,但 ORDER BY RAND() 大数据量时性能极差
  • 数值函数减少程序层计算,让数据处理更接近数据源

下一章引子:数值之外,字符串操作是另一类高频需求——拼接、截取、替换、格式化。

上一页
字符串函数
下一页
日期函数