where 子句中的日期时间
Posted
技术标签:
【中文标题】where 子句中的日期时间【英文标题】:Datetime in where clause 【发布时间】:2010-12-29 04:18:51 【问题描述】:如何在 sql 的 where
子句中选择 12/20/2008?
服务器是 SQL server 2005。
select * from tblErrorLog
where errorDate = '12/20/2008'
【问题讨论】:
errorDate
列是什么数据类型?
如果列数据类型确实是日期时间,上面的代码应该可以工作。
如果 SQL Server 上的日期格式未设置为 US,上述代码将不起作用。使用下面的 ts 方法实现区域独立性。
转换日期并明确其格式/类型会更安全,因为某些系统和代码会以不同方式读取日期。
【参考方案1】:
WHERE datetime_column >= '20081220 00:00:00.000'
AND datetime_column < '20081221 00:00:00.000'
【讨论】:
这不起作用,如果您使用这种方法,日期应该是 '2008-20-12'。 (yyyy-dd-mm)。如果使用 ts 标识符,这将是正确的格式。 @_J_:yyyy-MM-dd
格式确实适用于大多数情况,但不是所有情况。 @onupdatecascade:你是对的。我已更新我的答案以使用在所有情况下都安全的格式。
你应该真正使用 datetime_column >= '20081220' 和 datetime_column
【参考方案2】:
假设我们在谈论 SQL Server DateTime
注意:BETWEEN 包括范围的两端,所以从技术上讲,这种模式是错误的:
errorDate BETWEEN '12/20/2008' AND '12/21/2008'
对于这样的时间范围,我的首选方法是:
'20081220' <= errorDate AND errordate < '20081221'
使用通用索引(范围扫描、SARGable、无功能)并正确截取第二天的午夜,而不依赖于 SQL Server 的时间粒度(例如 23:59:59.997)
【讨论】:
我似乎对此投了反对票,我想知道为什么。如果您认为此解决方案不起作用,请教育我! 好吧,我只是在最初发布后的某个时间查看了这个,并注意到它不包括时间,还注意到 OP 也没有,但是你引用了 SQL 粒度。不过我投了赞成票,因为我也使用这种格式。【参考方案3】:使用转换函数获取特定日期的所有条目。
Select * from tblErrorLog where convert(date,errorDate,101) = '12/20/2008'
更多信息请见CAST and CONVERT
【讨论】:
这不是一个好方法,因为如果对列使用转换,则无法使用索引【参考方案4】:首先,我建议对日期/时间使用 ISO-8601 标准格式 - 无论您的 SQL Server 上的语言和区域设置如何,它都能正常工作。 ISO-8601 是 YYYYMMDD
格式 - 没有空格,没有破折号 - 只是数据:
select * from tblErrorLog
where errorDate = '20081220'
其次,您需要注意 SQL Server 2005 DATETIME
始终包含时间。如果您只检查日期部分是否完全匹配,您将只获得与时间 0:00:00 匹配的行 - 仅此而已。
您可以使用提到的任何推荐范围查询,或者在 SQL Server 2008 中,您可以使用 DATE
仅日期时间 - 或者您可以进行如下检查:
select * from tblErrorLog
where DAY(errorDate) = 20 AND MONTH(errorDate) = 12 AND YEAR(errorDate) = 2008
哪个最适合你。
如果您需要经常执行此查询,您可以尝试规范化 DATETIME
以仅包含日期,或者您可以为 DAY、MONTH 和 YEAR 添加计算列:
ALTER TABLE tblErrorLog
ADD ErrorDay AS DAY(ErrorDate) PERSISTED
ALTER TABLE tblErrorLog
ADD ErrorMonth AS MONTH(ErrorDate) PERSISTED
ALTER TABLE tblErrorLog
ADD ErrorYear AS YEAR(ErrorDate) PERSISTED
然后您可以更轻松地查询:
select * from tblErrorLog
where ErrorMonth = 5 AND ErrorYear = 2009
等等。由于这些字段是计算和持久化的,因此它们始终是最新的并且始终是最新的,并且由于它们是持久化的,因此您甚至可以根据需要对它们进行索引。
【讨论】:
十多年后,您的回答对我帮助很大。谢谢!!!【参考方案5】:你没有说你正在使用哪个数据库,但在 MS SQL Server 中它会是
WHERE DateField = d '2008-12-20'
如果是时间戳字段,则需要一个范围:
WHERE DateField BETWEEN ts '2008-12-20 00:00:00' AND ts '2008-12-20 23:59:59'
【讨论】:
不能按照 MS SQL Server 2005 中的描述/要求工作,我只是尝试过。令人惊讶的是它是有效的,它只是为您提供日期如上的结果,时间为 00:00:00 谢谢,原来的问题似乎只是一个没有时间的日期字段。为日期时间字段添加了范围。 @Meff 此语法适用于任何支持 ODBC 标量函数的数据库,而不仅仅是 MS SQL。然而,它所做的只是将常量的类型从字符串转换为日期。【参考方案6】:select * from tblErrorLog
where errorDate BETWEEN '12/20/2008' AND DATEADD(DAY, 1, '12/20/2008')
【讨论】:
以上是关于where 子句中的日期时间的主要内容,如果未能解决你的问题,请参考以下文章