统计三月份订单,写了 where create_time between 2024-03-01 and 2024-03-31,数字比财务少一截。3 月 31 日下午的单子全被漏掉,因为那个上界被当成了当天零点。
between 是闭区间,两端都算
它等价于大于等于左边、小于等于右边。字段是 date 类型时没事,一旦是 datetime,右边界会被补成当天 00:00:00,当天其余时间全掉在区间外面。
SELECT COUNT(*) FROM orders WHERE create_time BETWEEN '2024-03-01' AND '2024-03-31';日期范围改成左闭右开
惯用做法是下界取当月一号,上界写下个月一号,用小于号。这样不用纠结 23:59:59 后面还挂着毫秒,也不用为了补一秒写成 23:59:59.999。
SELECT COUNT(*) FROM orders WHERE create_time >= '2024-03-01' AND create_time < '2024-04-01';几个容易踩的边角
- 字符串和数字混着写会隐式转换,between 1 and 9 拿到的是字符串比较,10 会排到 2 前面。
- 字段是 NULL 时,between 和 not between 都不会返回这一行,别指望 not between 捞得出空值。
- 字段被函数包住,比如 date(create_time) between 两个值,索引直接失效,老老实实写范围比较。
- 字符串前缀查询受排序规则影响,大小写敏感的库里结果会不一样。
结论很直接:时间字段统一用左闭右开,别拿 between 碰月份边界;只有整数和纯日期类型才放心用闭区间。