BETWEEN查日期范围常少一天,因日期字符串被转为当日00:00:00导致右边界截断;应改用>= AND <方式,如created_at >= '2024-05-01' AND created_at < '2024-05-11'。

WHERE 条件里用 BETWEEN 查日期范围,为什么总少一天?
因为 BETWEEN 是闭区间,但多数人传的是「日期字符串」而非「完整时间戳」,数据库会自动补成当天的 00:00:00,导致右边界被截断。比如 '2024-05-10' BETWEEN '2024-05-01' AND '2024-05-10' 实际查的是 2024-05-10 00:00:00,而你想要的可能是 2024-05-10 23:59:59。
- 推荐改用
>= AND :写成 <code>created_at >= '2024-05-01' AND created_at ,逻辑清晰、索引友好、不依赖时区隐式转换 - 如果必须用
BETWEEN,右边手动加时间:BETWEEN '2024-05-01' AND '2024-05-10 23:59:59.999'(注意不同数据库毫秒精度不同,PostgreSQL 支持.999,MySQL 5.6 只到秒) - 避免直接比较字符串类型字段,哪怕它看起来像日期——先确认字段类型是
DATE、DATETIME还是TIMESTAMP,类型不匹配会导致全表扫描
MySQL 中把 Unix 时间戳转成可读日期,FROM_UNIXTIME() 和 UNIX_TIMESTAMP() 怎么配对用?
FROM_UNIXTIME() 是把整数秒转成 DATETIME,UNIX_TIMESTAMP() 是反向操作;但它们默认都按系统时区走,跨时区服务容易出错。
- 显式指定时区更安全:比如
FROM_UNIXTIME(1715299200, '+08:00')强制按东八区解析;反过来存的时候也用UNIX_TIMESTAMP(CONVERT_TZ('2024-05-10 12:00:00', '+08:00', '+00:00')) -
UNIX_TIMESTAMP()传入NULL返回当前时间戳,但传入空字符串或非法日期会返回0(即1970-01-01 00:00:00),查不到数据还难排查 - 如果字段是
TIMESTAMP类型,MySQL 内部存的是 UTC,读取时自动转本地时区——这时别再用FROM_UNIXTIME(UNIX_TIMESTAMP(col))套娃,纯属多余且慢
PostgreSQL 查询某天所有记录,::date 转换和 DATE() 函数哪个快?
用 col::date = '2024-05-10' 比 DATE(col) = '2024-05-10' 更可能走索引,因为前者是类型转换,后者是函数调用,PG 通常无法在函数结果上直接使用普通 B-tree 索引。
- 想让
DATE(col)也能走索引?建表达式索引:CREATE INDEX idx_orders_date ON orders (DATE(created_at)); -
col::date在 WHERE 里写没问题,但别在 UPDATE 或 INSERT 的 DEFAULT 里滥用,某些版本对表达式默认值支持有限 - 注意
col::date会丢掉时分秒,如果字段本身是TIMESTAMPTZ,转换前已按当前 session 时区调整过,确保 session 时区设置正确(SHOW timezone;)
SQL Server 处理带毫秒的时间范围,GETDATE() 和 SYSDATETIME() 差在哪?
GETDATE() 返回 DATETIME,精度只到 3.33 毫秒(实际存储为 0、3、7 结尾),而 SYSDATETIME() 返回 DATETIME2(7),精度达 100 纳秒。做高频时间戳比对或微秒级日志分析时,选错就丢精度。
- 用
SYSDATETIME()时,注意DATETIME2字段要声明足够精度,比如DATETIME2(3)只存毫秒,(7)才存纳秒 -
DATEADD(ms, -1, GETDATE())这种写法看似减 1 毫秒,实际可能变成减 3 毫秒(因内部四舍五入),换成DATEADD(ns, -1000000, SYSDATETIME())更准 - 跨版本迁移要注意:
DATETIME2在 SQL Server 2008+ 才支持,老系统用GETDATE()+ 补零逻辑反而更兼容
边界值从来不是“多试几次就能对”,而是得看清楚字段类型、函数行为、时区上下文、索引能力这四层嵌套影响。漏掉任何一层,查出来的数据就可能安静地错着。










