咱们今天聊一个数据库里特别基础,但又特别容易踩坑的东西——BETWEEN AND。很多新手刚学SQL的时候,看到这个语法,觉得挺直观的:“不就是查某个范围的数据吗?”比如查2023年1月到3月的订单,写个WHERE orderdate BETWEEN '2023-01-01' AND '2023-03-31',看起来没毛病。但真到实际项目里,你会发现这玩意儿藏着不少细节,搞不好就翻车。我见过一个同事,就因为BETWEEN AND没搞明白,线上查数据少算了好几天的记录,被业务部门追着问。今天咱们就掰开揉碎了聊聊这件事。

先说说BETWEEN AND最核心的逻辑:它是闭区间,包括两端。什么意思呢?就是你写WHERE age BETWEEN 18 AND 30,它会包括18岁和30岁的人。这一点跟很多人的直觉相反,因为日常说话里“18到30”有时候可能被理解成“18到29”,但SQL是实打实的。如果你查的是数值字段,比如成绩、价格、年龄,闭区间通常问题不大。但一旦碰上日期和时间,麻烦就来了。因为日期在数据库里存储的时候,往往带着时分秒。比方说orderdate字段是datetime类型,你写BETWEEN '2023-01-01' AND '2023-01-31',它只会包含'2023-01-31 00:00:00'这个瞬间,而1月31日当天下午三点下的单,就全被漏掉了。这个坑,我敢说80%的开发者都踩过。
解决这个问题,常见的方法有几种。一是把结束日期加一天,比如BETWEEN '2023-01-01' AND '2023-02-01',然后查询条件里用< '2023-02-01',这样就能覆盖到1月31日一秒。二是直接用>=和<的组合,比如WHERE orderdate >= '2023-01-01' AND orderdate < '2023-02-01',这样既清晰又不会漏数据。三是把日期字段转换成纯日期格式,比如用DATE()函数把datetime转成date再比较,但这样会影响索引性能,数据量大时慎用。我自己的习惯是,只要涉及日期范围查询,一律用>=和<,虽然多敲几个字,但心里踏实。BETWEEN AND这种语法,我基本只用在整数、金额这种明确不含小数位的字段上。
再说一个容易忽略的点:BETWEEN AND跟索引的关系。很多人以为加了索引,查询就快,但BETWEEN AND在某些情况下会让索引失效。比如你查的字段是varchar类型,但存的是数字,像'001'、'002'这种,BETWEEN AND会按字符串排序来比较,结果可能跟你想象的不一样。字符串'10'比'2'小,因为按字典序,'1'排在'2'前面。所以如果你在字符串字段上用BETWEEN AND查数字范围,数据库可能会走全表扫描。还有个场景是复合索引,比如索引建在(category, price)上,你只查price BETWEEN 100 AND 200,但条件里没带category,索引可能就用不上。这时候数据库得回表查,效率打折。
聊到这儿,你可能觉得BETWEEN AND挺麻烦的,但它在某些场景下确实有优势。比如查某个时间段内的统计数据,像“2023年第一季度”,你写BETWEEN '2023-01-01' AND '2023-03-31',一眼就能看出是三个月,比用>=和<要直观。还有做报表的时候,业务人员要理解SQL,BETWEEN AND对他们来说更友好。所以我觉得,关键不是不用它,而是知道什么时候能用、什么时候得避开。如果你能确保字段类型是date(不带时分秒),或者你明确知道两端的数据都有效,那就放心用。否则,多写几行代码,总比线上出bug强。
说个实战经验。有一次我在处理一个千万级的订单表,业务要拉去年一年的数据,写了BETWEEN '2022-01-01' AND '2022-12-31'。结果跑出来少了12月31日那天的所有订单,因为那天是周六,很多订单都是晚上下的,时分秒都大于'00:00:00'。后来改成>= '2022-01-01' AND < '2023-01-01',数据才完整。这件事让我养成了一个习惯:凡是日期范围查询,不管字段是date还是datetime,一律用>=和<。而且我会在代码注释里写清楚,防止后来接手的人踩坑。数据库这东西,看起来简单,但细节里全是坑。BETWEEN AND就像一把双刃剑,用好了顺手,用不好伤手。所以我的建议是:多测试,多思考边界情况,别让语法糖变成绊脚石。


