使用Between与datetime类型的select语句不会检索所有字段?

时间:2011-03-26 08:51:09

标签: sql sql-server datetime

我面临着一个奇怪的查询结果,我想问你为什么我要面对这个问题。

我将一些日期时间数据存储到 TestTable 中,如下所示:

creation_time
-----------------------
2010-07-10 00:01:43.000
2010-07-11 00:01:43.000
2010-07-12 00:01:43.000

此表格已创建并填写如下:

create table TestTable(creation_time datetime);
Insert into  TestTable values('2010-07-10 00:01:43.000');
Insert into  TestTable values('2010-07-11 00:01:43.000');
Insert into  TestTable values('2010-07-12 00:01:43.000');

当我执行此查询时,我只得到两行而不是我预期的三行:

SELECT *  FROM TestTable
WHERE  creation_time BETWEEN  CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
                     and      CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part  

或者,如果我执行此查询,同样的问题..

SELECT *  FROM TestTable
WHERE  CONVERT(datetime,creation_time,111) BETWEEN  CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
                                              and      CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part

我的问题:

  • 为什么最后一行('2010-07-12 00:01:43.000')没有出现在 结果即使我将日期范围设置为从 2010-07-10到2010-07-12 全天覆盖?
  • 我使用带有Windows xp 32位的Sql server 2005 express版。
  • 我正在尝试不使用解决方案,例如增加日期范围以覆盖额外的一天以获得我想要的日子。

谢谢。

5 个答案:

答案 0 :(得分:1)

您还需要从creation_time中删除时间部分。如果有效,请使用相同的CONVERT

目前你问的是2010-07-12 00:01:43.000是否小于2010-07-12 00:00:00.000,这不是真的。

答案 1 :(得分:1)

它没有显示日期,因为您删除了时间部分,这会使日期等同于'2010-07-12 00:00:00.000',并且因为最后一行大于此,所以它不会显示在查询结果中。 / p>

答案 2 :(得分:1)

您的脚本应如下所示:

SELECT * 
FROM TestTable
WHERE  creation_time BETWEEN
  convert(datetime, convert(char, '2010-07-10', 106))-- remove time part
  and **DATEADD**(day, 1, convert(datetime, convert(char, '2010-07-**11**', 106))) -- remove time part and add 1 day

此脚本将在2010-07-10 00:00:00和2010-07-12 00:00:00之间返回。基本上这意味着在2天内创建的所有项目:2010-07-10和2010-07-11。

答案 3 :(得分:1)

转换表中的列进行比较可能代价高昂,导致索引无法使用。如果您的表中有一百万行,并且您在creation_time上有索引,那么您将进行索引扫描并将所有百万个值转换为字符串以进行比较。

我发现最好使用> =开始日期和< (结束日期+ 1天):

SELECT *
FROM TestTable
WHERE creation_time >= '2010-07-10'
    AND creation_time < dateadd(day, 1, '2010-07-12')

你的第二个可能不起作用的原因是因为格式111使用斜杠(“2010/07/10”),格式120使用破折号(“2010-07-10”)。您的转换器没有对您的开始和结束日期做任何事情,因为您要将字符串转换为varchar,而不是日期。如果你这样做,它可能会有效,但我仍然建议不要进行转换:

SELECT * FROM TestTable
WHERE CONVERT(datetime, creation_time, 111) BETWEEN
    CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-10'), 111) -- remove time part
    and CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-12'), 111) -- remove time part

答案 4 :(得分:0)

2010年7月10日至2010年12月7日期间的日期/时间:

SELECT *  FROM TestTable 
WHERE  creation_time BETWEEN  
 CONVERT(VARCHAR,'2010-07-10',101) -- remove time part                      
  and CONVERT(VARCHAR,'2010-07-13',101) -- remove time part