我正在使用sql Server 2000中的T-sql,我有一个表TRANSACTIONS,其日期列TRANDATE定义为DateTime,其中许多列与此问题无关.
该表填充了多年的交易.我遇到了代码,测试,让我感到困惑.有一个简单的SELECT,像这样:
SELECT TRANDATE,RECEIPTNUMBER FROM TRANSACTIONS WHERE TRANDATE BETWEEN '12/01/2010' and '12/31/2010' ORDER BY TRANDATE
并且它不返回我知道在该表中的两行数据.
通过上面的语句,它按顺序返回的最后一行有一个TRANDATE:
2010-12-31 00:00:00.000
当我修改如下所示的语句时,我得到了该表中2010年12月的额外两行:
SELECT TRANDATE,RECEIPTNUMBER FROM TRANSACTIONS WHERE TRANDATE BETWEEN '12/01/2010 00:00:00' and '12/31/2010 23:59:59' ORDER BY TRANDATE
我试图找出为什么BETWEEN运算符在使用上面的第一个SELECT时在12/31/2010的24个周期内不包括所有行.为什么它需要将明确的小时数添加到SELECT语句中,如同在第二个修改后的语句中一样,以使其拉出正确的行数?
是因为TRANDATE定义为“DATETIME”的方式?
基于这个发现,我认为我将不得不经历所有这些旧代码,因为这些BETWEEN运算符遍布这个旧系统,似乎它没有正确地提取所有数据.我只想先从一些人那里得到澄清.谢谢!
解决方法
日期是一个时间点,而不是时间跨度.
’12 / 31/2010’也是一个观点.也就是说,这是十二月三十一日的午夜.
在这一点之后发生的一切都被忽略了.
这正是你想要的行为(即使你还没有意识到).
不要以为当你选择省略时间部分时,它被神奇地假设为“任何”.这将是“全部为零”,即午夜.
如果您想在查询中包含整天,而不必指定23:59:59(顺便说一下,excludes the last second of the day,在当天23:59:59到00:00:00之间)第二天),您可以使用严格的不等式(>,<)来限制您不想要的第一个时间点:
WHERE TRANDATE >='12/01/2010 00:00:00' and TRANDATE < '01/01/2011'
或者通过比较投放到DATE的日期值:
WHERE CAST(TRANDATE AS DATE) between '12/01/2010' and '12/31/2010'
(可以将这种类型的强制转换放在WHERE子句中,it is sargable).