表里搜表:SQL 日期条件的几种“土味”用法 别总想着用那种“起初、其次、最终”的教科书式开场白,在写 SQL 日期条件的时候,直接把这玩意儿扔进代码里,看效果就行。 就比如我一直拖着一个 2023 年的用户表,想看看哪位在 2024 年 3 月 15 日那天才注册,用 `WHERE date_col > '2024-03-15'` 这个写法,查到的结局一般比你想象的多。出于 `>` 是大于号,只要日期比 15 号晚,哪怕那是 15 号晚上 23 点,要么 16 号凌晨 1 点,全算进去。
这就害得有时候查的结局比预期多一大截,排查难题的时候好办头大。
那如何查“正好是”呢?那就得用 `>=` 和 `<=`。
比如想查在 3 月 15 日这天注册的人,写 `WHERE date_col >= '2024-03-15' AND date_col < '2024-04-01'`,这样就把工夫范围死死钉死在 15 号这个切片上。 再说说 `BETWEEN` 这个家伙,它在大量场景下简直是神来之笔。之前有个需求,我要找所有在 2024 年 3 月 1 日到 4 月 31 日之间注册过的用户,这时候要是用 `>` 和 `<` 就得写两行,就连还得寻思两个边界值分别用 `>=` 和 `<` 的情况,好办出错。直接用 `WHERE date_col BETWEEN '2024-03-01' AND '2024-04-31'` 一行搞定,既简洁又精准。
不管是要早于 2024 年 5 月 31 日,还是晚于 2024 年 3 月 1 日,用这两个词儿一合计,范围就出来了。就像买菜,只要在这个工夫段内买到的菜,不管具体是几点买的,只要落在 3 到 4 月这档子里,都算上。
不过这里要注意,日期字符串比较的时候,要是格式不一致,可能会乱套,最好统一格式要么转成毫秒数再比,不然好办出小丝瑕。 有时候我们只想看“那会儿”的日子,不想看“未来”,这时候用 `AND date_col < CURRENT_DATE` 是个挺实用的技巧。`CURRENT_DATE` 这个函数是数据库自带的,直接调用,不用自己去调库。
比如我想看所有在 2024 年 3 月 15 日之前注册的用户,`WHERE date_col < CURRENT_DATE` 要么 `AND date_col < '2024-03-15 23:59:59'`。
注意看,这个条件务必配合主查询的日期字段一起用,否则别看逻辑是对的,但数据库可能不知道该把哪个列当成日期比较。 还有一种情况,就是日期在字符串里的表现形式,比如 `DATE` 型字段时常是 `YYYY-MM-DD`,有时候为了显示撇脱,会存成 `YYYYMMDD` 要么小写的 `yyyy-mm-dd`。
这时候直接拿 `>` 或 `<` 比,要是格式不同,比如一个是 `2024-03-15`,另一个是 `2024-03-15 10:30:00`,别看逻辑上它们代表同一天,但 SQL 引擎可能把 `2024-03-15 10:30:00` 这个更大的字符串当做“晚于”来评判。
故此要是不确定数据库是按字符串比较还是按数值比较,用 `EXTRACT` 函数要么 `CAST` 转为标准格式比较稳妥。
比如 `EXTRACT(DAY FROM date_col) >= DATE '2024-03-15'`,这样就能把任何格式的字符串都归一化,直接按天数比。 实际上大量时候,我们并不需求复杂的日期过滤,而是想通过日期来把表过滤器掉,剩下的数据更干净利落。
比如所有 2024 年 3 月 15 日当天 12 点赶明儿不再更新的数据表,要是直接用 `date_col > '2024-03-15 12:00:00'` 加上 `UPDATE_TIME > '2024-03-15 12:00:00'`,就能直接过滤掉所有 3 月 15 日 12 点之前已经更新过的记录。
这大大削减了回的行数,速度最快。自然,要是表量挺大,这种切片操作可能会害得临时表要么中间内存占用过高,这时候能够寻思用窗口函数要么子查询,比如 `WHERE date_col < '2024-03-15 12:00:00'` 配合 `ROW_NUMBER()` 要么 `RANK()` 函数,把那些日期早于阈值的记录给捞出来,再在应用层做二次筛选。 另外,别忘了比较时别漏了 `NULL` 值。`NULL` 在 SQL 里归于“无值”,不能直接参与数学运算,也不能和任何值比较大小。
故此 `WHERE date_col > '2024-03-15'` 这个条件,要是表里与此同时存了 `NULL` 和正式日期,结局可能会是空的,要么全回,要么只回那些大于 15 号的,取决于数据库的具体实现。
严格来说,`NULL > '2024-03-15'` 一辈子回 `FALSE`。
故此写日期条件的时候,尽量用 `IS NOT NULL` 来兜底,要么在应用层做预处理,把 `NULL` 过滤掉,再在 SQL 里写 `AND date_col IS NOT NULL`。
这样写起来别看啰嗦一点,但能避免那些莫名其妙的 `False` 结局,让代码逻辑跑得更顺。 最终再唠叨一句,日期比较最怕字符陷阱。
比如 `LIKE` 里面带日期,那个 `%` 号是匹配任何字符,包含数字。
要是你写 `WHERE date_col LIKE '2024-03'`,那么 `'2024-03-15'` 和 `'2024-03-abc'` 都会被匹配到,这可能是你意想不到的。
故此只能用 `>` `<` `BETWEEN` `AND` 这种比较运算符,不要用 `LIKE` 去碰日期字符串。
要是要做不清楚匹配,比如找大致在这个范围的人,那就得用函数取出来的具体数值,要么把日期字段特殊格式处理成纯数字再比。 总而言之,日期条件在 SQL 里别看看起来复杂,实际上核心就两点:定范围,去不清楚。范围用 `BETWEEN` 或 `AND` `>` `<` 就能搞定,不清楚用函数取再比较。
只要不把 `NULL` 当回事,不用死记硬背那些“起初其次”的废话,直接上代码,让数据库自己帮你算,代码自然就烂熟于心了。


相关标签: