EP09. "常用数字与日期函数速查(MySQL vs SQL Server)"
🔒 登录后可标记已读- 数字函数(ROUND / ABS / CEILING / FLOOR / POWER)两边语法几乎一模一样,反而是日期函数从函数名到参数顺序都不一样,混用最容易出错
- 涵盖 5 个数字函数 + 6 个日期函数,例子沿用 EP01 / EP02 的 users / orders / products 电商场景
- 日期函数尤其要注意:MySQL 用 NOW() / DATE_ADD(),SQL Server 用 GETDATE() / DATEADD(),两边函数名完全不同,连参数顺序都相反
- 前置知识:先看过 EP01 的 SELECT 基本语法
重点内容
数字函数类
| 用途 | MySQL | SQL Server | 例子 |
|---|---|---|---|
| 四舍五入 | ROUND(num, decimals) | ROUND(num, decimals, [operation]) | ROUND(49.999, 2) |
| 取绝对值 | ABS(num) | ABS(num) | ABS(-15.5) |
| 无条件进位 | CEILING(num) | CEILING(num) | CEILING(50.0/12) |
| 无条件舍去 | FLOOR(num) | FLOOR(num) | FLOOR(349.9/100) |
| 次方 | POWER(x, y) | POWER(x, y) | POWER(2, 3) |
四舍五入:ROUND
折扣算完价格常常会出现一堆小数,显示给用户看之前要 round 到 2 位小数:
-- 两边语法相同,price 算出来是 49.999,四舍五入显示成 RM 50.00
SELECT ROUND(price, 2) AS display_price
FROM products
WHERE id = 501;
📌 SQL Server 的 ROUND() 多一个第三参数 operation:留空或填 0 是正常四舍五入,填非 0 的值会变成直接砍掉小数(truncate),不是四舍五入——不小心传错第三个参数,结果会跟预期不一样。
取绝对值:ABS
盘点的时候,系统库存跟实际库存对不上,不管是多了还是少了,先取绝对差值判断严重程度:
-- 两边语法相同
SELECT product_id, ABS(system_qty - actual_qty) AS diff
FROM stock_check
WHERE ABS(system_qty - actual_qty) > 5;
无条件进位:CEILING
一箱能装 12 件商品,订单有 50 件,要算需要几箱:
-- 注意:50、12 如果是整数栏位,SQL Server 的整数除法会先把 50/12 truncate 成 4,
-- CEILING 再套上去还是 4,不是想要的 5,要先转成 decimal 再除(写成 50.0/12)
SELECT CEILING(50.0 / 12) AS boxes_needed;
-- 结果:5
无条件舍去:FLOOR
会员消费满 RM 100 升一级,用 FLOOR 算出目前该在第几级:
-- 两边语法相同,消费 RM 349.90,FLOOR(349.90/100) = 3,算出目前是第 3 级
SELECT FLOOR(total_spent / 100) AS member_tier
FROM users
WHERE id = 1001;
次方:POWER
推荐奖励活动规则是每多拉一层下线,奖励翻倍(2 的 N 次方):
-- 两边语法相同,base_bonus = RM 10,拉到第 3 层,奖励 = 10 * 2^3 = RM 80
SELECT 10 * POWER(2, referral_level) AS bonus_amount
FROM referrals
WHERE user_id = 1001;
日期函数类
| 用途 | MySQL | SQL Server | 例子 |
|---|---|---|---|
| 取当前日期时间 | NOW() | GETDATE() | 插入订单时间戳 |
| 日期加减 | DATE_ADD(date, INTERVAL n unit) | DATEADD(unit, n, date) | 算预计到货日 |
| 计算日期差 | DATEDIFF(date1, date2) | DATEDIFF(unit, date1, date2) | 算订单距今几天 |
| 格式化日期 | DATE_FORMAT(date, format) | FORMAT(date, format) | 按年月分组报表 |
| 取年份 | YEAR(date) | YEAR(date) | 抓某年订单 |
| 取月份 | MONTH(date) | MONTH(date) | 抓某月订单 |
取当前日期时间:NOW() vs GETDATE()
-- MySQL:新订单入库,记录建立时间
INSERT INTO orders (user_id, total_amount, created_at) VALUES (1001, 158.00, NOW());
-- SQL Server:函数名不一样,其他写法相同
INSERT INTO orders (user_id, total_amount, created_at) VALUES (1001, 158.00, GETDATE());
日期加减:DATE_ADD vs DATEADD
下单后预计 3 天到货:
-- MySQL:date 放第一个参数,INTERVAL 数值+单位放后面
SELECT order_no, DATE_ADD(created_at, INTERVAL 3 DAY) AS expected_arrival
FROM orders
WHERE id = 5001;
-- SQL Server:单位跟数值放前面,date 放最后——跟 MySQL 参数顺序刚好相反
SELECT order_no, DATEADD(day, 3, created_at) AS expected_arrival
FROM orders
WHERE id = 5001;
📌 两个函数不只是名字不同,参数顺序也不一样:MySQL 是「日期在前、间隔在后」,SQL Server 是「间隔在前、日期在后」,照抄很容易漏改顺序。
计算日期差:DATEDIFF
算一笔订单距离现在下单了几天:
-- MySQL:只有两个参数,日期1 - 日期2,结果是天数(想算天数,要把较晚的日期放前面)
SELECT order_no, DATEDIFF(NOW(), created_at) AS days_since_order
FROM orders
WHERE id = 5001;
-- SQL Server:三个参数,第一个是单位;日期顺序是"较早的放前面",结果 = 后面日期 - 前面日期
SELECT order_no, DATEDIFF(day, created_at, GETDATE()) AS days_since_order
FROM orders
WHERE id = 5001;
📌 这两个函数的日期顺序刚好相反:MySQL 要把「较晚的日期」放第一个参数才能得到正数天数;SQL Server 反过来,要把「较早的日期」放前面。顺序搬错,算出来的天数会变成负数。
格式化日期:DATE_FORMAT vs FORMAT
抓出本月新注册的用户,按年月分组做报表:
-- MySQL:格式字符串用 % 开头的占位符
SELECT DATE_FORMAT(created_at, '%Y-%m') AS signup_month, COUNT(*) AS new_users
FROM users
GROUP BY DATE_FORMAT(created_at, '%Y-%m');
-- SQL Server:格式字符串用 .NET 风格(yyyy-MM),跟 MySQL 完全不同语法
SELECT FORMAT(created_at, 'yyyy-MM') AS signup_month, COUNT(*) AS new_users
FROM users
GROUP BY FORMAT(created_at, 'yyyy-MM');
💡 FORMAT() 语法比老写法(CONVERT() 拼字符串)好读,但处理大量数据时效能通常比较差,正式环境资料量大时,格式化建议留到应用层(后端代码)处理,不要在 SQL 里对一大批资料跑 FORMAT()。
取年份/月份:YEAR / MONTH
两边函数名一样,直接抓某年某月的订单:
-- 两边语法相同
SELECT * FROM orders
WHERE YEAR(created_at) = 2026 AND MONTH(created_at) = 8;
常见错误
- ❌ 把 MySQL 的
NOW()直接搬到 SQL Server 用——SQL Server 要用GETDATE(),反过来也一样会报错,两个函数名完全不通用 - ❌
DATE_ADD/DATEADD参数顺序搬错——MySQL 是「日期, INTERVAL 数值 单位」,SQL Server 是「单位, 数值, 日期」,顺序刚好相反 - ❌
DATEDIFF的日期顺序搬错,算出负数天数——MySQL 要把「较晚日期」放前面,SQL Server 要把「较早日期」放前面,两边逻辑相反 - ❌ SQL Server 的 DATEDIFF 忘记传单位参数——MySQL 只要两个日期就够(固定算天数),SQL Server 一定要多给一个
day/month/year之类的单位,少一个参数直接报错 - ❌ 用
WHERE DATE_FORMAT(created_at, '%Y-%m') = '2026-08'或WHERE FORMAT(created_at, 'yyyy-MM') = '2026-08'当过滤条件——这类函数会让栏位上的索引失效,数据量大时会变成全表扫描;实务上更常用WHERE created_at >= '2026-08-01' AND created_at < '2026-09-01'这种范围查询,或WHERE YEAR(created_at) = 2026 AND MONTH(created_at) = 8 - 💡 SQL Server 的
ROUND()第三个参数不是 0 时会变成截断而不是四舍五入,容易手滑传错
Sources
Blog / Website:
- MySQL ROUND
- MySQL ABS
- MySQL CEILING
- MySQL FLOOR
- MySQL POWER
- MySQL NOW
- MySQL DATE_ADD
- MySQL DATEDIFF
- MySQL DATE_FORMAT
- MySQL YEAR
- MySQL MONTH
- SQL Server ROUND
- SQL Server ABS
- SQL Server CEILING
- SQL Server FLOOR
- SQL Server POWER
- SQL Server GETDATE
- SQL Server DATEADD
- SQL Server DATEDIFF
- SQL Server FORMAT
- SQL Server YEAR
- SQL Server MONTH