PC TOOLS

EP09. "常用数字与日期函数速查(MySQL vs SQL Server)"

首页 PC 工具 Calculating · SQL · EP09
约 14 分钟· #EP09#SQL
🔒 登录后可标记已读
  • 数字函数(ROUND / ABS / CEILING / FLOOR / POWER)两边语法几乎一模一样,反而是日期函数从函数名到参数顺序都不一样,混用最容易出错
  • 涵盖 5 个数字函数 + 6 个日期函数,例子沿用 EP01 / EP02 的 users / orders / products 电商场景
  • 日期函数尤其要注意:MySQL 用 NOW() / DATE_ADD(),SQL Server 用 GETDATE() / DATEADD(),两边函数名完全不同,连参数顺序都相反
  • 前置知识:先看过 EP01 的 SELECT 基本语法

重点内容


数字函数类

用途MySQLSQL 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;

日期函数类

用途MySQLSQL 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:

  1. MySQL ROUND
  2. MySQL ABS
  3. MySQL CEILING
  4. MySQL FLOOR
  5. MySQL POWER
  6. MySQL NOW
  7. MySQL DATE_ADD
  8. MySQL DATEDIFF
  9. MySQL DATE_FORMAT
  10. MySQL YEAR
  11. MySQL MONTH
  12. SQL Server ROUND
  13. SQL Server ABS
  14. SQL Server CEILING
  15. SQL Server FLOOR
  16. SQL Server POWER
  17. SQL Server GETDATE
  18. SQL Server DATEADD
  19. SQL Server DATEDIFF
  20. SQL Server FORMAT
  21. SQL Server YEAR
  22. SQL Server MONTH