SQL Server 2008 DateTime范围查询

9

我有一个名为Users的表:

创建时间 用户名
2012-08-30 14:23:12:000
2012-08-30 15:11:13:000
2012-08-30 16:32:22:000
2012-08-31 11:23:12:000 史蒂文
2012-08-31 12:05:14:000
2012-08-31 08:23:12:000 ddd

还有一个查询:

select UserName 
from Users  
where CreateTime >= '2012-08-30' and CreateTime <= '2012-08-31' 

所以,结果应该是6行,但实际上不是。

如何解决这个问题?

使用SQL Server的Convert函数CONVERT(VARCHAR(23), CreateTime, 121)


你的CreateTime列是一个dateTime列?你应该在WHERE子句中也使用datetype(目前你使用了一个字符串,这往往是它无法正常工作的原因)。编辑:使用类似于CAST('01-JAN-2009' AS DATETIME)的东西。 - Najzero
不正确。在 ANSI SQL 中,字符串非常适合表示日期/时间。他的查询只有三个字符错误,下面还有多个正确的解决方案。 - dodexahedron
7个回答

19

它没有显示6行,因为解释器将2012-08-31视为2012-08-31 00:00:00 AM。由于您想看到包括31号在内的数据,您可以明确地提及时间或查询第二天的日期。

使用第二天的日期的示例

SELECT UserName 
FROM Users  
WHERE CreateTime >= '2012-08-30' AND CreateTime < '2012-09-01'

显式提及时间的示例

SELECT UserName 
FROM Users  
WHERE CreateTime >= '2012-08-30 00:00:00' AND CreateTime < '2012-09-31 23:59:59'

在你的第二个查询中,你应该使用<=而不是<来包括一天中的最后一秒:... and CreateTime <= '2012-09-31 23:59:59' - Filip Cornelissen

16

你所需要做的就是将CreateTimeDatetime转换为Date,方法如下:CAST

SELECT  UserName FROM Users 
WHERE CAST(CreateTime as date)>='2012-08-30' 
AND CAST(CreateTime as date)<= '2012-08-31';

您还可以像这样使用BETWEEN代替<=>=

SELECT  UserName FROM Users 
WHERE CAST(CreateTime as date) BETWEEN 
'2012-08-30' AND '2012-08-31';

请查看这个 SQLFiddle


2
由于CreateTime列是一个DATETIME列,我可能会使用CAST(CreateTime AS DATE)而不是指定一个字符串格式/样式进行转换。 - marc_s
1
@marc_s 你是对的。当列数据类型为 DATETIME 时,我们应该使用 CAST 而不是 CONVERT。已更新答案。 - Himanshu
2
如果你在数据库的CreateTime值上使用CAST,那么它会干扰索引,导致查询运行缓慢。 - Vince Bowdren

3
基本问题在于,当您仅输入日期时,SQL Server会将该日期解释为该日期的午夜。因此,当您要求“2012-08-31”时,实际上意味着“2012-08-31 12:00AM”。
最好的解决方案是选择比您想要的日期晚一天,并使用小于号,而不是小于或等于号。
select  UserName from  Users  where CreateTime>='2012-08-30' and CreateTime < '2012-09-01'

0

试试这个

select  UserName 
from  Users  
where CreateTime>='2012-08-30' and CreateTime<'2012-09-01'

1
第二个条件中的“小于等于”会超出范围,应该只使用“小于”。 - dodexahedron
哦,忘记删除那个符号了。 - hgulyan

0
select  UserName from  Users  where CreateTime>='2012-08-30' and CreateTime < '2012-09-01'

2
请正确格式化您的源代码,不要只是复制别人的答案。 - Thorsten Dittmar
你好Thorsten Dittmar,我该如何做这件事? - Rejeesh
2
在这个时候,大多数情况下是通过删除答案来解决的。这里已经有多个正确的解决方案的副本了。将来,为了正确地格式化代码,请选择您在表单中键入的代码,然后单击看起来像两个花括号({ })的按钮。这将缩进文本,告诉StackOverflow在页面中将其格式化为代码。 - dodexahedron

0

CreateTime<='2012-08-31'对于最后三个日期永远不为真,因为它们的时间戳是在午夜之后。 2012-08-31表示2012-08-31 00:00:00,所以只返回前三行。

您应该始终包括时间戳-此外:使用其他答案中建议的BETWEEN是一个好主意。


0
你应该使用类似下面的代码:
SELECT UserName 
 FROM Users 
WHERE DATEDIFF(d, '2012-08-30', CreateTime) >= 0 
  AND DATEDIFF(d, @ToDate, '2012-09-01') <=0

使用这个查询,你将不再需要花费时间去计算小时和分钟。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接