在SQL Server中将日期字符串与日期时间进行比较?

52
在 SQL Server 中,我有一个包含时间元素的 DATETIME 列。

示例:

'14 AUG 2008 14:23:019'

最好的方法是什么,可以只选择特定日期的记录,无视时间部分?

示例:(不安全,因为它不匹配时间部分并且不返回任何行)

DECLARE  @p_date DATETIME
SET      @p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )

SELECT *
FROM   table1
WHERE  column_datetime = @p_date

注意:由于这个网站也是用来记录笔记和你学到却又遗忘的技术,我将发布我的答案到这个问题作为DATETIME在MSSQL中最常查询的主题之一。


更新:更明确地阐述示例。


编辑:抱歉,但我不得不给出错误答案(返回错误结果)的回答打下分。

@Jorrit:WHERE (date>'20080813' AND date<'20080815')会返回13号和14号。

@wearejimbo:接近了,但还差一点! 给你颁发荣誉徽章。你错过了 08/14/2008 23:59:001 到 23:59:999 写入的记录(即午夜前不到1秒的时间)。

18个回答

39

技术一:

 DECLARE @p_date DATETIME
 SET     @p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )

 SELECT  *
 FROM    table1
 WHERE   column_datetime >= @p_date
 AND     column_datetime < DATEADD(d, 1, @p_date)

这样做的好处是,如果存在“column_datetime”上的任何索引,它都会使用该索引。


12
我认为将'14 AUG 2008'转换为DateTime类型使用CAST()略好一些。我认为这种方式更易读,并且CAST()比CONVERT()更具可移植性,因为CAST()与ANSI SQL-92和-99兼容。 - Larry OBrien
1
你可以使用BETWEEN关键字作为这个答案的速记。 - Möoz
1
@BorhanMooz,实际上,BETWEEN 不会捕捉到代码中给出的 >= / < 之间的跨度。BETWEEN 是完全包容的(http://technet.microsoft.com/en-us/library/ms187922.aspx,“结果值”)。 - Bondolin

20

在SQL Server 2008中,您可以使用新的DATE数据类型。

DECLARE @pDate DATE='2008-08-14'  

SELECT colA, colB
FROM table1
WHERE convert(date, colDateTime) = @pDate  

@Guy。我认为你会发现这个解决方案很好扩展。请查看您原始查询的查询执行计划

至于我的查询


8

只需要比较年、月和日的值。

Declare @DateToSearch DateTime
Set @DateToSearch = '14 AUG 2008'

SELECT * 
FROM table1
WHERE Year(column_datetime) = Year(@DateToSearch)
      AND Month(column_datetime) = Month(@DateToSearch)
      AND Day(column_datetime) = Day(@DateToSearch)

4

在您接受的答案中,指出了索引的好处。

然而,如果您确实经常只搜索特定的日期日期范围,那么我找到的最佳解决方案是向您的表中添加另一个持久化计算列,该列仅包含日期,并在此列上添加索引:

ALTER TABLE "table1" 
    ADD "column_date" AS CONVERT(DATE, "column_datetime") PERSISTED

在该列上添加索引:
CREATE NONCLUSTERED INDEX "table1_column_date_nu_nci"
ON  "table1" ( "column_date" ASC )
GO

那么你的搜索将会更快:
DECLARE  @p_date DATE
SET      @p_date = CONVERT( DATE, '14 AUG 2008', 106 )

SELECT   *
FROM     table1
WHERE    column_date = @p_date

然后,我建议使用ISO日期格式之一,大多数数据库都能识别,并且不依赖于语言/区域设置,例如YYYY-MM-DD - van

4

我通常会将日期时间转换为日期并进行比较,例如:

SELECT 'Same Date' WHERE CAST(getDate() as date) = cast('2/24/2012 2:23 PM' as date)

或者

SELECT 'Same Date' WHERE DATEDIFF(dd, cast(getDate() as date), cast('2/24/2012 2:23 PM' as date)) = 0

4

技巧2:

DECLARE @p_date DATETIME
SET     @p_date = CONVERT( DATETIME, '14 AUG 2008', 106 )

SELECT  *
FROM    table1
WHERE   DATEDIFF( d, column_datetime, @p_date ) = 0

如果column_datetime字段没有建立索引,而且不太可能建立(或者索引不太可能被使用),那么使用DATEDIFF()会更短。

4
像这样的内容吗?
SELECT  *
FROM    table1
WHERE   convert(varchar, column_datetime, 111) = '2008/08/14'

3

这个函数Cast(Floor(Cast(GetDate() As Float)) As DateTime)返回一个日期时间数据类型,其中时间部分被删除,可以像这样使用。

Select
*
Table1
Where
Cast(Floor(Cast(Column_DateTime As Float)) As DateTime) = '14-AUG-2008'

或者

DECLARE  @p_date DATETIME
SET      @p_date = Cast('14 AUG 2008' as DateTime)

SELECT   *
FROM     table1
WHERE    Cast(Floor(Cast(column_datetime As Float)) As DateTime) = @p_date

如果应用于字段(如果索引),多个函数将不会将其转换为完整的表扫描吗? - Manuel Ferreria

3

如何在MS SQL Server中获取DATETIME字段的日期部分:

最快、最简洁的方法之一是使用

DATEADD(dd, DATEDIFF( dd, 0, @DAY ), 0)

它避免了将日期转换为字符串并再次转换的CPU繁重逻辑。
它还不会暴露内部实现,即“时间部分表示为日期的分数”。
获取本月第一天的日期
DATEADD(dd, DATEDIFF( dd, -1, GetDate() - DAY(GetDate()) ), 0)

获取一年前的日期

DATEADD(m,-12,DATEADD(dd, DATEDIFF( dd, -1, GetDate() - DAY(GetDate()) ), 0))

1
DECLARE @Dat

SELECT * 
FROM Jai
WHERE                                                                                                          
CONVERT(VARCHAR(2),DATEPART("dd",Date)) +'/'+                                                              
             CONVERT(VARCHAR(2),DATEPART("mm",Date)) +'/'+              
                     CONVERT(VARCHAR(4), DATEPART("yy",Date)) = @Dat

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