between在日期查询中默认包含边界值,但需确保字段类型为date或datetime;若为varchar,须转日期类型再比较,且应避免用between查datetime字段的全天范围,推荐>=与

BETWEEN 在日期查询中默认包含边界值,但必须确保字段类型和格式完全匹配,否则可能查不到数据或范围错误。
确认 date 字段实际类型是 DATE 或 DATETIME
很多问题其实出在字段类型上:order_date 看似存日期,实际可能是 VARCHAR。用 SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='orders' AND COLUMN_NAME='order_date'; 查一下。如果是字符串,BETWEEN '2024-01-01' AND '2024-01-31' 可能因字典序比较而失效(比如 '2024-01-10' 会被认为大于 '2024-01-31'?不,但 '2024-01-5' 就会乱序)。务必先转成日期类型再比,例如 WHERE DATE(order_date) BETWEEN '2024-01-01' AND '2024-01-31' —— 但注意这会让索引失效。
使用标准 ISO 格式字符串('YYYY-MM-DD')避免时区/解析歧义
MySQL、PostgreSQL、SQL Server 都接受 '2024-01-01',但拒绝 '01/01/2024'(取决于 sql_mode 或区域设置)。尤其当字段是 DATETIME 时,BETWEEN '2024-01-01' AND '2024-01-31' 实际等价于 BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 00:00:00',会漏掉 31 号全天数据。正确写法应为:
WHERE order_date >= '2024-01-01' AND order_date <p>—— 这才是安全覆盖整月的写法;若坚持用 <code>BETWEEN</code>,则需显式补时间:<code>BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 23:59:59'</code>,但后者在毫秒精度下仍可能丢数据。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/ai/1981" title="千图设计室AI助手"><img src="https://img.php.cn/upload/ai_manual/000/000/000/175680175167215.png" alt="千图设计室AI助手" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/ai/1981" title="千图设计室AI助手" class="overflowclass">千图设计室AI助手</a> <p class="overflowclass">一款面向图片创作与处理的AI工具,可提供图片生成、放大、擦除、抠图和修复等能力,满足日常视觉内容制作需求。</p> </div> <a rel="nofollow" href="/ai/1981" title="千图设计室AI助手" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <h3>注意不同数据库对 BETWEEN 的 NULL 处理一致,但函数行为有差异</h3> <p><code>BETWEEN a AND b</code> 本身等价于 <code>value >= a AND value ,所有主流数据库对 <code>NULL</code> 都返回 <code>UNKNOWN</code>(即不匹配),这点统一。但日期函数要小心:</code></p>
- MySQL 支持
DATE('2024-01-01 14:30:00')直接截取日期部分 - PostgreSQL 要写
order_date::DATE或DATE(order_date) - SQL Server 推荐用
CAST(order_date AS DATE),不用CONVERT(VARCHAR, ...)再比字符串
一旦用了函数包装字段(如 DATE(order_date)),就无法走 order_date 上的索引——除非建函数索引(PostgreSQL/MySQL 8.0.13+ 支持)。
最常被忽略的是:BETWEEN 看似简单,但日期字段带时间、存储类型非原生、跨数据库迁移时默认格式变化——这三个点任一出问题,查询结果就“看起来没错,其实少数据”。动手前先 SELECT MIN(order_date), MAX(order_date) FROM orders LIMIT 5; 看一眼真实值长什么样。










