题 如何仅从SQL Server DateTime数据类型返回日期


SELECT GETDATE()

返回: 2008-09-22 15:24:13.790

我希望那个日期部分没有时间部分: 2008-09-22 00:00:00.000

我怎么能得到它?


1409
2017-09-22 03:31


起源


如果你想要一个没有时间的日期数据类型,即使时间是00:00:00然后你运气不好,你可以得到一个varchar,但结构是一个日期时间,你将总是有一些时间。 - Quintin Robinson
需要注意的一点是,SQL Server 2008包含一个单独的DATE数据类型,用于存储没有时间组件的日期。更多信息: sql-server-performance.com/articles/dev/datetime_2008_p1.aspx - Ben Hoffstein
不要错过 这个帖子 显示各种时间去除方法的性能测试结果。 - ErikE
不要被投票和接受的答案误导,看一看 stackoverflow.com/a/126984/1155650 - Rohit Vipin Mathews
@Rohit你错误地认为2008年是人们唯一关心的版本。 (野外还有更多版本。)投票不言自明。 - hktegner


答案:


SQL Server 2008 更高,你应该 CONVERT 至今:

SELECT CONVERT(date, getdate())

在旧版本上,您可以执行以下操作:

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, @your_date))

例如

SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

给我

2008-09-22 00:00:00.000

优点:

  • 没有 varchar< - >datetime 需要转换
  • 无需考虑 locale

2061
2017-09-22 03:34



+1看起来这个比通常使用的double convert()方法快35%(我也使用了多年)。好一个。 - Dane
我能看到你的解决方案唯一的缺点是,除非你知道它在做什么,否则它有点迟钝。使用双转换方法可以使你的意图更加明显地为代码维护者提供服务。顺便说一下,我没有低估你。我想我也会开始使用你的方法。谢谢@aku - Jim Birchall
@pilavdzice将日期时间设置为当天午夜 不 离开时间。你期待什么结果?该 datetime 数据类型不能有 没有时间。我认为您将数据存储与用户演示混淆。如果您想要的是一种向用户显示没有时间部分的字符串(不是零,只是空白)的方法,那么您只需要 Convert(varchar(30), @Date, 101) 或类似的东西。看到 SQL Server联机丛书•转换和转换 了解更多信息。 - ErikE
@ user1671639日期时间数据类型始终包含日期和时间,您无法合理地存储一个日期和时间 - 除非您使用的是SQL Server 2008,在这种情况下还有单独的“日期”和“时间”数据类型。如果你像这样使用CONVERT(),你真的想要一个字符串供以后使用,所以你会被困在那样做 - 尽管如果你使用日期格式化函数而不是关闭日期会更好 - 或者通过 CAST(... AS DATE) 要么 CONVERT(DATE, ...)在这个页面上经常被提及。 - Magnus
我建议将答案改为 SELECT DATEADD(dd, DATEDIFF(dd, 0, @your_date), 0) 因为那时候 dd 可以换掉任何其他的 datepart 截断你的关键字 datetime 任意级别。 - Michael


SQLServer 2008现在具有“日期”数据类型,该类型仅包含没有时间组件的日期。使用SQLServer 2008及更高版本的任何人都可以执行以下操作:

SELECT CONVERT(date, GETDATE())

657
2017-09-24 13:02



SQL2008中还有'time'数据类型,它解决了分离日期和时间问题的另一半问题。 - misteraidan
仅供参考,我对从日期修剪时间的不同方法进行了基准测试,这是最快的方法。虽然这种差异很小,但在很多次执行中显然更快。 - UnhandledExcepSean
wt关于sqlserver 2005 ?? - Dr. MAF
@ Dr.MAF完成这个圈子,2008年之前的答案就在这里: stackoverflow.com/questions/113045/... - Frosty840


如果使用SQL 2008及更高版本:

select cast(getdate() as date)

141
2018-01-31 09:44



@FredrickGauss:什么类型,日期?您使用的是哪个版本的SQL Server? - abatishchev
谨防!声明@ date1 datetime ='2015-09-30 20:59:59.999'; select cast(@ date1 as date)返回'2015-10-01' - Nick
@Nick:这是DateTime的问题。使用 DateTime2 相反,它工作正常。 sqlfiddle.com/#!6/9eecb7/2833 - abatishchev
@Nick,为了补充abatishchev的反应,你的@ date1确实如此 2015-10-01, 由于 DateTime 限制。尝试没有任何演员 Date它产生了 2015-10-01太! declare @date1 datetime = '2015-09-30 23:59:59.999';select @date1 => 2015-10-01 - Frédéric
其中一个容易记住的SQL技巧。正如迈克所说,只有2008年才开始,但是,如果你在某个地方找到2005和以前的数据库,你可能会遇到很多问题:) - NicVerAZ


DATEADD和DATEDIFF优于CONVERTing到varchar。两个查询都有相同的执行计划,但执行计划主要是关于 数据 访问策略并不总是揭示执行所有部分所花费的CPU时间所涉及的隐式成本。如果两个查询都针对具有数百万行的表运行,则使用DateDiff的CPU时间可能接近转换CPU时间的1/3!

要查看查询的执行计划:

set showplan_text on
GO 

DATEADD和DATEDIFF都将执行CONVERT_IMPLICIT。

虽然CONVERT解决方案更简单,更容易阅读,但它  比较慢。无需转换回日期时间(这由服务器隐式完成)。之后DateDiff方法中也没有真正需要DateAdd,因为整数结果也将被隐式转换回datetime。


SELECT CONVERT(varchar,MyDate,101)FROM DatesTable

  |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(varchar(30),[TEST].[dbo].[DatesTable].[MyDate],101)))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

SELECT DATEADD(dd,0,DATEDIFF(dd,0,MyDate))FROM DatesTable

  |--Compute Scalar(DEFINE:([Expr1004]=dateadd(day,(0),CONVERT_IMPLICIT(datetime,datediff(day,'1900-01-01 00:00:00.000',CONVERT_IMPLICIT(datetime,[TEST].[dbo].[DatesTable].[MyDate],0)),0))))
       |--Table Scan(OBJECT:([TEST].[dbo].[DatesTable]))

使用FLOOR()作为@digi建议的性能更接近DateDiff,但不建议将datetime数据类型转换为float并且返回并不总是产生原始值。

记住伙计们:不要相信任何人。查看性能统计信息,并自行测试!

在测试结果时要小心。为客户端选择多行将隐藏性能差异,因为通过网络发送行所需的时间比执行计算所需的时间长。因此,请确保所有行的工作都由服务器完成,但没有行集发送到客户端。

某些人似乎对缓存优化何时影响查询感到困惑。在同一批次或不同批次中运行两个查询对缓存没有影响。因此,您可以手动使缓存过期,也可以只是多次来回运行查询。查询#2的任何优化也会影响任何后续查询,因此如果您愿意,请抛弃执行#1。

这是 完整的测试脚本和性能结果 证明DateDiff比转换为varchar快得多。


67
2017-09-22 03:33



里卡多C,很好的调查!你使用什么版本的SQL服务器?在使用datediff的MSSQL2000方法上,对我来说执行速度稍快。 - aku
需要注意的是,我进行了1000.000次测试。对于真实场景,性能差异不会明显,我想 - aku
Aku,我使用SQL Server 2005 Express进行此测试。我在2000年工作,我将用一个超过2400万行的表来测试它,看看它是什么。 - Ricardo C
阿库,结果相同。超过一千万行的性能没有差异。 - Ricardo C
关于同等表现的主张并非如此。当然执行计划也一样!!!测量这些性能必须通过比较CPU使用率而不是检查执行计划来完成。 - ErikE


SELECT CONVERT(VARCHAR(10),GETDATE(),111)

41
2017-09-22 03:33



这将为我返回'2008/09/22' - eddiegroves
111是日文格式。 YYY / MM / DD - Ricardo C
SELECT CONVERT(VARCHAR(10),GETDATE(),101)是 mm/dd/yyyy 格式。 - Flea
如果你是根据原始文本值(在DB之外)进行排序,那么'japanese'格式会更好 - Simon_Weaver
它适用于SQL Server 2005。 - Raphael Amoedo


SELECT CONVERT(datetime, CONVERT(varchar, GETDATE(), 101))

35
2017-09-22 03:34





你可以使用 CONVERT 函数只返回日期。请参阅以下链接:

SQL Server 2000中的日期和时间操作

CAST和CONVERT

使用convert函数的语法是:

CONVERT ( data_type [ ( length ) ] , expression [ , style ] ) 

18
2017-12-19 06:48