在SQL Server中删除部分date时间的最佳方法

从SQL Server中的date时间字段中删除时间部分时哪种方法提供最佳性能?

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0) 

要么

 b) select cast(convert(char(11), getdate(), 113) as datetime) 

第二种方法确实发送了几个字节,但这可能不如转换速度那么重要。

两者似乎都非常快,但在处理数百或数千行时,速度可能会有所不同。

另外,是否有更好的方法来摆脱SQL中的date时间部分?

严格来说,方法a是资源密集度最低的:

 a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0) 

在相同的总持续时间内,经过validation的CPU占用时间减less了一百万行,手中有太多时间: SQL Server中从date+时间获取date的最有效方法?

我在其他地方也看到了类似的testing,结果也是类似

我更喜欢DATEADD / DATEDIFF,因为:

  • varchar受到语言/date格式问题的影响
    示例: 为什么我的CASEexpression式不确定?
  • 浮动依赖于内部存储
  • 它通过改变“0”基数来延伸到制定出月份的第一天,明天等

编辑,2011年10月

对于SQL Server 2008+,可以CAST date 。 或者只是使用date所以没有时间去除。

编辑,2012年1月

这是一个灵活的工作示例: 需要通过在SQL Server中舍入时间或date图来计算

编辑,2012年5月

不要在WHERE子句和类似的东西中使用它,而不考虑:向列添加函数或CAST会使索引使用无效。 在这里看2号: http : //www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/

现在,这确实有一个后来的SQL Server优化版本pipe理CAST的date正确的例子,但通常这将是一个坏主意…

在SQL Server 2008中,您可以使用:

 CONVERT(DATE, getdate(), 101) 

当然,这是一个古老的线程,但要完成。

从SQL 2008中,您可以使用DATE数据types,以便您可以简单地执行:

 SELECT CONVERT(DATE,GETDATE()) 
 SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME) 

这是另外一个重复问题的答案:

 SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

这个神奇数字方法执行比DATEADD方法稍快。 (看起来〜10%)

CPU时间几百万logging:

 DATEADD MAGIC FLOAT 500 453 453 360 375 375 406 360 

但请注意,这些数字可能是不相关的,因为它们已经非常快了。 除非我有100,000或更多的logging集,否则我甚至无法将CPU时间读取到零以上。

考虑到DateAdd是为了这个目的,而且更健壮的事实,我会说使用DateAdd。

在SQL Server 2008中,有一个DATE datetype(也是一个TIME数据types)。

 CAST(GetDate() as DATE) 

要么

 declare @Dt as DATE = GetDate() 
 SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME) 

首先解决插入/更新时间问题。 对于即时转换,没有任何东西可以胜任用户定义的function:

 select date_only(dd) 

date_only的实现可以是任何你喜欢的 – 现在它被抽象出来,调用代码要干净得多。

看到这个问题:
我如何截断SQL Server中的date时间?

不pipe你做什么, 都不要使用string方法 。 这是你可以做到的最糟糕的方式。

已经回答,但不幸的是,这也扔出去了…这suposely也preform很好,但它的工作原理是从float中丢掉小数(存储时间),只返回整个部分(这是date)

  CAST( FLOOR( CAST( GETDATE() AS FLOAT ) ) AS DATETIME ) 

第二次,我发现这个解决scheme… 我抓住了这个代码

 CAST(round(cast(getdate()as real),0,1) AS datetime) 

此方法不使用string函数。 Date基本上是一个真正的数据types,小数点之前的数字是一天中的一小部分。

这个我估计会比很多。

对我来说,下面的代码永远是赢家:

 SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE()))); 

selectCONVERT(char(10),GetDate(),126)

我认为你的意思是cast(floor(cast(getdate()as float))as datetime)

真正的只有32位,可能会丢失一些信息

这是最快的cast(cast(getdate()+x-0.5 as int)as datetime)

…虽然只有大约10%的速度(about 0.49 microseconds CPU vs. 0.58)

这是推荐,并在我的testing刚刚在同一时间: DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

在SQL 2008中,SQL CLR函数的速度比使用SQL函数的速度快大约5倍,在1.35微秒和6.5微秒之间,表明SQL CLR函数与简单的SQL UDF的函数调用开销要低得多。

在SQL 2005中,根据我的testing,SQL CLR函数比这个慢函数快了16倍:

 create function dateonly ( @dt datetime ) returns datetime as begin return cast(floor(cast(@dt as float))as int) end 

谨防!

方法a)和b)不总是有相同的输出!

 select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0) 

输出: 2014-01-01 00:00:00.000

 select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime) 

产出: 2013-12-31 00:00:00.000

(在MS SQL Server 2005和2008 R2上testing)

编辑:根据Adam的评论,如果您从表中读取date值,则不会发生这种情况,但是如果您将date值作为文字(例如:作为通过ADO.NET调用的存储过程的参数)提供,则可能会发生这种情况。

如何select cast(cast my_datetime_field as date) as datetime) ? 这导致相同的date,时间设置为00:00,但避免任何转换为​​文本,也避免任何明确的数字四舍五入。

我认为,如果你坚持使用TSQL ,这是截断时间最快的方法:

  select convert(datetime,convert(int,convert(float,[Modified]))) 

我发现这个截断方法比DateAdd方法快大约5%。 这可以很容易地修改到最近的一天,如下所示:

 select convert(datetime,ROUND(convert(float,[Modified]),0)) 

如果可能的话,对于这样的特殊情况,我喜欢使用CLR函数。

在这种情况下:

 [Microsoft.SqlServer.Server.SqlFunction] public static SqlDateTime DateOnly(SqlDateTime input) { if (!input.IsNull) { SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0); return dt; } else return SqlDateTime.Null; } 

我个人几乎总是使用用户定义的函数来处理SQL Server 2005(或更低的版本),但是,应该注意的是,使用UDF有特定的缺陷,特别是如果将它们应用到WHERE子句(见下面和进一步的细节在这个答案的意见)。 如果使用SQL Server 2008(或更高版本) – 请参阅下文。

实际上,对于我创build的大部分数据库,我都会在开始时添加这些UDF,因为我知道有99%的机会迟早会需要它们。

我创build了“仅限date”和“仅限时间”(尽pipe“仅限date”是迄今为止最常用的两个)。

以下是与各种与date相关的UDF的链接:

基本的SQL Serverdate,时间和date时间函数
取得datefunction

最后一个链接显示了不less于3种不同的方法来获取date时间字段的一部分,并提到每种方法的优点和缺点。

如果使用UDF,应该注意,您应该尽量避免将UDF用作查询中的WHERE子句的一部分,因为这会极大地妨碍查询的性能。 主要原因是在WHERE子句中使用UDF会将该子句呈现为非sargable ,这意味着SQL Server不能再使用具有该子句的索引来提高查询执行的速度。 关于我自己对UDF的用法,我经常使用WHERE子句中的“raw”date列,但是将UDF应用到SELECTed列。 这样,UDF只应用于过滤结果集,而不是表的每一行作为filter的一部分。

当然,绝对最好的方法是使用SQL Server 2008(或更高版本)并分离出date和时间 ,因为SQL Server数据库引擎然后本地提供单独的date和时间组件,并且可以高效地独立地查询这些而不需要UDF或其他机制从复合date时间types中提取date或时间部分。

在这里我做了一个函数来删除SQL Server的date时间的一些部分。 用法:

  • 第一个参数是被剥离的date时间。
  • 第二个参数是char:
    • 秒:几秒钟; 消除毫秒
    • 米:轮到分钟; 删除秒和毫秒
    • h:几个小时; 删除分钟,秒和毫秒。
    • d:几天到几天; 删除小时,分钟,秒和毫秒。
  • 返回新的date时间

create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end

以防万一任何人在这里寻找一个Sybase版本,因为以上几个版本不起作用

 CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME) 
  • 在Adaptive Server 15.7上运行的I SQL v11中进行了testing

我很喜欢:

 [date] = CONVERT(VARCHAR(10), GETDATE(), 120) 

120格式代码将把date强制转换为ISO 8601标准:

 'YYYY-MM-DD' or '2017-01-09' 

在dplyr( R )和pandas( Python )中使用超级简单!

我会用:

 CAST ( CAST(YEAR(DATEFIELD) as varchar(4)) + '/' CAST(MM(DATEFIELD) as varchar(2)) + '/' CAST(DD(DATEFIELD) as varchar(2)) as datetime ) 

因此,从您已有的date字段有效地创build一个新的字段。