如何在SQL Server 2012中筛选含NULL值的datetime数据?
问题分析与解决方案
你的SQL查询之所以会过滤掉timeout为NULL的记录,主要有两个关键问题:
1. 错误的NULL值判断逻辑
你用了cast(logouttime as date) <= ''来试图匹配NULL,但这完全不成立:
- 当
logouttime是NULL时,CAST(logouttime AS DATE)的结果也是NULL,而在SQL中,NULL和任何值(包括空字符串)比较都会返回UNKNOWN,不会被OR条件匹配到。 - 日期类型和空字符串
''本身就没有可比性,这个条件逻辑上就是错误的,根本无法起到筛选NULL的作用。
2. 条件组合排除了NULL记录
原查询的(cast(Logouttime as date) <= '2018-05-16' or cast(logouttime as date) <= '')部分,对于timeout为NULL的记录,两个子条件都不成立,所以这部分记录会被整个WHERE条件排除。
正确的查询写法
要包含timeout为NULL的记录,你需要用IS NULL来直接判断NULL值,这是SQL中处理NULL的标准方式。这里提供两种优化方案:
方案1:保留CAST的写法(适合需要日期维度筛选的场景)
SELECT * FROM tb_user_log WHERE CAST(timein AS DATE) >= '2018-05-16' AND (CAST(timeout AS DATE) <= '2018-05-16' OR timeout IS NULL) ORDER BY id DESC;
方案2:避免CAST,利用索引提升性能(推荐)
如果timein和timeout字段有索引,使用CAST会让索引失效,导致查询变慢。可以直接用datetime范围来筛选:
SELECT * FROM tb_user_log WHERE timein >= '2018-05-16' -- 匹配2018-05-16当天及之前的所有时间,或者timeout为NULL AND (timeout < DATEADD(day, 1, '2018-05-16') OR timeout IS NULL) ORDER BY id DESC;
这里用DATEADD(day, 1, '2018-05-16')得到2018-05-17 00:00:00,timeout <这个值就能准确匹配所有2018-05-16当天的记录,比用<= '2018-05-16 23:59:59.997'更稳妥,避免因SQL Server datetime的精度问题漏掉记录。
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

