资讯动态

面试官:MySQL BETWEEN AND 语句包括边界吗?

发布时间:2026/10/16 3:03:36 来源:尧图企业网站定制
使用数据库时我们经常会用到范围查询今天来聊一聊 MySQL 的 BETWEEN AND 语句。1.是否包含边界为了说明 BETWEEN AND 语句是否包括边界我们先创建一张表SQL 如下CREATE TABLEtest3 ( idint(8) NOTNULL AUTO_INCREMENT, avarchar(10) COLLATE utf8_bin DEFAULTNULL, bvarchar(10) COLLATE utf8_bin DEFAULTNULL, datedateDEFAULTNULL, date_time datetime DEFAULTNULL, time_stamptimestampNULLDEFAULTNULL, PRIMARY KEY (id), KEYidx_a (a) ) ENGINEInnoDB AUTO_INCREMENT11DEFAULTCHARSETutf8 COLLATEutf8_bin我们插入 10 条数据如下图1.1 执行结果对 id 做范围查询SELECT * FROM test3 WHERE id BETWEEN 2 AND 6;查询结果如下可以看到对 id 做范围查询包含了边界值 2 和 6是一个闭区间。对 date 做范围查询SELECT * FROM test3 WHERE DATE BETWEEN 2025-08-28 AND 2025-08-31;查询结果如下可以看到对 date 类型的字段进行范围查询同样包含了边界值是一个闭区间。对 date_time 做范围查询SELECT * FROM test3 WHERE date_time BETWEEN 2025-08-28 AND 2025-08-31;对 date_time 使用日期做范围查询查询结果如下可以看到这个查询漏掉了 2025-08-31 这一天的数据是一个前闭后开的区间。这是因为 MySQL 会自动将日期的时间部分补充为零点所以上面的查询语句等价于SELECT * FROM test3 WHERE date_time BETWEEN 2025-08-28 00:00:00 AND 2025-08-31 00:00:00;为了不漏掉数据可以将上面的查询语句改为SELECT * FROM test3 WHERE DATE BETWEEN 2025-08-28 AND 2025-09-01;对 time_stamp 使用日期做范围查询结果跟 date_time 一样。1.2 总结BETWEEN AND 语句是包括边界值的是一个前闭后闭的区间。BETWEEN A AND B 等价于 A AND B。注意时间类型的字段DATETIME 和 TIMESTAMP如果采用日期格式来查询结果是前闭后开的区间。BETWEEN A AND B 等价于 A AND B。为了避免漏掉数据datetime 和 timestamp 使用日期做范围查询可以在后面的日期上加 1 天。2.原理2.1 执行器优化对于 BETWEEN AND 语句MySQL 优化器会在早期优化时把它优化成等值查询所以下面查询 SQLSELECT * FROM test3 WHERE id BETWEEN 2 AND 6;在优化器看来完全等价与SELECT * FROM test3 WHERE id 2 AND id 6;两个 SQL 在性能上没有差别。2.2 性能索引范围扫描如果 BETWEEN AND 语句的字段上有索引则可以使用索引进行范围扫描效率很高。我们看一下上面一个 SQL 执行计划如下EXPLAIN SELECT * FROM test3 WHERE id BETWEEN 2 AND 6;typerange代码使用到了索引进行范围扫描查询过程如下存储引擎从索引树的根节点开始找到第一个 id 2 的索引条目。这个操作时间复杂度是 O(log n)非常高效从上面找到的第一个索引条目开始沿着索引树的叶子节点向后顺序扫描当遇到第一个 id 6 的索引条目时停止扫描存储引擎给执行器返回结果集。全表扫描如果 BETWEEN AND 语句的字段上没有索引只能进行全表扫描比如下面的语句EXPLAIN SELECT * FROM test3 WHERE b BETWEEN 30 AND 50;我们看一下执行计划这就需要扫描表中的每一行记录逐一判断字段 b 的值是否落在 [30, 50] 这个区间内。这个执行效率非常低。非主键索引跟等值查询不同的是即使 BETWEEN AND 语句的字段加了普通索引如果查询的字段用不上覆盖索引也会走全表扫描。如下面的语句EXPLAIN SELECT * FROM test3 WHERE a BETWEEN 30 AND 50;虽然字段 a 上面有普通索引但是查询的是表 test3 中的所有字段也是走不上 a 这个索引的。我们看一下执行计划复合索引我们再看一下复合索引的情况我们新建一张表SQL 如下CREATE TABLEtest4 ( idint(8) NOTNULL AUTO_INCREMENT, avarchar(10) COLLATE utf8_bin DEFAULTNULL, bvarchar(10) COLLATE utf8_bin DEFAULTNULL, datedateDEFAULTNULL, date_time datetime DEFAULTNULL, time_stamptimestampNULLDEFAULTNULL, PRIMARY KEY (id), KEYidx_a_b (a, b) ) ENGINEInnoDB AUTO_INCREMENT11DEFAULTCHARSETutf8 COLLATEutf8_bin在 test4 这张表上我们建一个字段(a,b)的复合索引。 BETWEEN AND 语句是可以用最左前缀原则的。如果我们执行下面 SQLSELECT a,b,id FROM test4 WHERE a BETWEEN 2 AND 6 AND b 3;复合索引的第一列 a 使用了范围查询第二列 b 作等值查询。MySQL 可以利用索引快速找到字段 a 在范围[2, 6]之间的数据然后在这些结果中筛选出 b 3 的记录。这种情况下字段 a 使用了索引但是字段 b 没有用上索引。如果我们执行下面 SQLSELECT a,b,id FROM test4 WHERE a 3 and b BETWEEN 2 AND 6;复合索引的第一列 a 使用了等值查询第二列 b 做范围查询。这种情况也是可以走上索引的。如果我们执行下面 SQLSELECT a,b,id FROM test4 WHERE b BETWEEN 2 AND 6;这种情况不符合最左前缀原则所以是走不上索引的。索引下推使用 BETWEEN AND 语句不能走索引下推。我们再来创建一张表CREATE TABLEtest_temp ( idINT(11) NOTNULLDEFAULT0, aVARCHAR(20) DEFAULTNULL, bVARCHAR(10) DEFAULTNULL, cVARCHAR(10) DEFAULTNULL, dVARCHAR(10) DEFAULTNULL, PRIMARY KEY (id), KEYa_b(a,b) ) ENGINEINNODBDEFAULTCHARSETutf8插入几条数据INSERT INTO test_temp VALUES(100, 10, 20, 2, 1); INSERT INTO test_temp VALUES(200, 10, 40, 4, 2); INSERT INTO test_temp VALUES(300, 10, 30, 3, 3); INSERT INTO test_temp VALUES(400, 40, 10, 1, 4);如果我们执行下面的 SQL是不能走索引下推的EXPLAIN SELECT * FROM test_temp WHERE a BETWEEN 10 AND 50 AND b 50;执行计划如下而如果我们把 SQL 改成EXPLAIN SELECT * FROM test_temp WHERE a 10 AND a 50 AND b 50;执行计划如下可以看到用上了索引下推。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑