计算列是什么
计算列是在 SELECT 里直接用表达式算出来的派生列,支持括号、四则运算与取模。它只存在于本次结果集,不会写回表,也没有对应索引。运算符优先级与数学一致:乘除取模高于加减,同级从左到右,括号可以改变顺序。整数除法与除零的行为在 MySQL 与 PostgreSQL 之间不同,涉及金额、比率、均值的计算要特别留意类型,必要时先做显式类型转换。
基本信息
| 运算符 | + - * / %(整除可用 DIV,取模也可写 MOD(a,b)) |
|---|---|
| 优先级 | * / % 高于 + -,同级从左到右 |
| NULL 参与 | 任一操作数为 NULL,结果即为 NULL |
| 除零 | MySQL 返回 NULL 并告警;PostgreSQL 直接报 division by zero |
| 整数除法 | MySQL 得小数;PostgreSQL 两整数相除截断 |
| 适用平台 | 标准 SQL 写法,MySQL 8.0 与 PostgreSQL 均支持 |
典型使用场景
- 算金额与小计:price * qty AS amount,避免前端重复实现口径
- 算含税价与折扣:先乘再加再 ROUND,注意舍入位置
- 算占比与差额:part * 100.0 / total,乘 100.0 规避整数除法
- 算分页偏移:偏移量等于页码减一乘以每页条数
- 算账龄与逾期天数:配合日期函数得到天数区间
- 归一化展示:把存储值换算成业务单位后再输出
示例
示例
SELECT item_id,
price, # 单价
qty, # 数量
price * qty AS amount, # 小计
ROUND(price * qty * 0.06, 2) AS tax, # 税额保留两位
(price * qty - discount) AS payable # 括号改变优先级
FROM order_items;整数除法与除零
整数除法与除零
-- MySQL:整数相除得到小数
SELECT 5 / 2; # 2.5000
SELECT 7 DIV 2; # 3,整除用 DIV
-- PostgreSQL:整数相除会截断
SELECT 5 / 2; # 2
SELECT 5::numeric / 2; # 2.5000000000000000
-- 除零:先兜底再计算
SELECT 1 / NULLIF(denominator, 0); # 分母为 0 时整体返回 NULL表达式与结果类型
| 表达式 | 结果 | 注意事项 |
|---|---|---|
| price * qty | 乘积 | 两整数列相乘仍是整数,超范围会溢出 |
| amount * 1.06 | 小数 | 常量是浮点字面量,金额应改用定点类型 |
| ROUND(x, 2) | 四舍五入到两位 | 只改变精度,不改变底层类型 |
| ABS(a - b) | 差值绝对值 | 对账比差常用 |
| MOD(a, b) | 余数 | b 为 0 时 MySQL 返回 NULL |
除数为 0 时 MySQL 返回 NULL 并给出告警,PostgreSQL 直接中断语句;业务计算前用 NULLIF 兜底分母最稳妥。
PostgreSQL 中两个整数列相除会截断小数,比率与均值计算要先 CAST 成 numeric,或乘一个带小数点的常量。
FLOAT 与 DOUBLE 是近似值,0.1 加 0.2 不等于 0.3;涉及金额、税率、库存数量的运算统一用 DECIMAL 或 numeric。
使用要点
- 给计算列起别名,后续 ORDER BY 与上层引用都更清楚
- 表达式里的列无法用普通索引过滤,WHERE 中把计算移到常量一侧
- 同一条 SQL 里重复用到的表达式提取成别名或 CTE
- 金额相关运算全程用定点类型,最后一步再按要求舍入
- 结果涉及除法时先想清楚分母为 0 与 NULL 的处理方式
- 业务口径写进注释或文档,避免同一指标在不同查询里算法不同