mysql需用date_sub(now(), interval 7 day)构造下界,禁用date(now())-7等错误写法;postgresql推荐(current_date - interval '7 days')保持类型一致;sql server宜用dateadd(day, datediff(day, 0, getdate()) - 7, 0)截断时间;须注意时区、null值及索引失效问题。

MySQL 中用 DATE_SUB 配合 WHERE 筛选近7天
MySQL 没有直接的 “7天前” 字面函数,得靠 DATE_SUB(NOW(), INTERVAL 7 DAY) 构造时间下界。注意别用 DATE(NOW()) - 7 这种算术减法——它会把日期转成整数再减,结果完全不可靠。
常见错误是写成:WHERE created_at > NOW() - INTERVAL 7 DAY(少了个括号),实际应为:WHERE created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)。另外,如果 created_at 是 DATETIME 或 TIMESTAMP 类型,且你希望包含“今天刚创建”的数据,用 > 就够了;若想包含 7 天前 00:00:00 那一刻,改用 >= 更稳妥。
PostgreSQL 里用 CURRENT_DATE 减整数更简洁
PostgreSQL 支持直接用 CURRENT_DATE - 7 得到日期值,不用嵌套函数。但要注意:这个表达式返回的是 DATE 类型,而你的 created_at 很可能是 TIMESTAMP WITH TIME ZONE。直接比较会导致隐式类型转换,可能跳过索引。
推荐写法是:WHERE created_at >= (CURRENT_DATE - INTERVAL '7 days')。这里用 INTERVAL 明确单位,且保持类型一致。如果表数据量大,确保 created_at 字段上有索引,否则全表扫描不可避免。
SQL Server 的 DATEADD 容易漏掉时区和精度
SQL Server 常见写法是 DATEADD(day, -7, GETDATE()),但它返回带时分秒的 DATETIME,而你可能只想比对“日期部分”。比如用户是今天 23:59 创建的,GETDATE() 当前是明天 00:01,那 DATEADD 结果就是“7天前的 00:01”,会漏掉昨天全天的数据。
安全做法是先截断时间:WHERE created_at >= DATEADD(day, -7, CAST(CAST(GETDATE() AS DATE) AS DATETIME)),或者更清晰地用:WHERE created_at >= DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 7, 0)。后者利用 DATEDIFF(day, 0, ...) 把时间归零,再加回去,兼容性更好。
通用陷阱:时区、索引失效和 NULL 值
几乎所有数据库都默认按服务器本地时区解析时间函数,如果你的应用部署在 UTC,而数据库设的是 CST,NOW() 和业务时间就差 8 小时,查出来的“近7天”可能错位一整天。
容易被忽略的点:
- created_at 字段允许 NULL?记得加 AND created_at IS NOT NULL,否则 NULL > xxx 判定为 UNKNOWN,该行直接被过滤
- 在 WHERE 中对 created_at 做函数运算(如 DATE(created_at) > ...)会让索引失效,必须避免
- 如果用 ORM(如 Django ORM、MyBatis),确认生成的 SQL 是否真用了字段索引,而不是把时间计算逻辑推到应用层做循环过滤











