SQL查询无法返回指定日期范围内的数据问题排查
问题根源与解决方案
哦,这个坑我之前踩过!问题出在你的「Date of Payment」列是nvarchar(50)字符串类型,而非日期类型——字符串的比较逻辑和日期完全不一样,导致BETWEEN的判断完全不符合你的预期。
为什么会返回2013年的数据?
字符串比较是从左到右逐字符按ASCII值对比,而不是按日期的时间顺序。举个例子:
'1/1/2017'的第二个字符是/(ASCII码47)'10/1/2013'的第二个字符是0(ASCII码48)
因为47 < 48,所以字符串层面'1/1/2017' < '10/1/2013';同时'10/1/2013'的前两位10小于'12/31/2017'的12,所以它会被BETWEEN '1/1/2017' AND '12/31/2017'包含进去,这就是你拿到非2017年数据的原因。
两种解决方案
1. 最优方案:修改列类型为日期类型
这是一劳永逸的办法,彻底解决字符串存日期的各种问题(比如无效日期、性能差、逻辑错误):
- 先验证所有字符串都能正常转换为日期:
这个查询会找出所有无法转换为有效日期的行,先处理这些脏数据。SELECT ID, [Date of Payment] FROM tblData WHERE TRY_CONVERT(DATE, [Date of Payment]) IS NULL - 修改列类型:
之后你的原查询就能正常工作,还能给该列加日期索引提升查询性能。ALTER TABLE tblData ALTER COLUMN [Date of Payment] DATE;
2. 临时方案:查询时转换为日期
如果暂时不能修改表结构,就在查询中把字符串转换为日期后再比较:
SELECT ID, [Date of Payment] FROM tblData WHERE TRY_CONVERT(DATE, [Date of Payment]) BETWEEN '2017-01-01' AND '2017-12-31'
- 用
TRY_CONVERT而非CONVERT,避免因为无效日期导致整个查询报错; - 建议用
YYYY-MM-DD这种ISO标准日期格式,避免因数据库语言/区域设置导致转换错误。
额外提醒
用字符串存储日期是非常不好的实践:
- 容易存入无效值(比如
'13/13/2017') - 无法利用日期索引,查询性能差
- 会出现各种逻辑错误(就像你现在遇到的)
内容的提问来源于stack exchange,提问作者user1342164
相关产品推荐
相关产品推荐

