我如何截断SQL Server中的date时间?

在SQL Server 2008中截断date时间值的最佳方法是什么(以消除小时和分钟)?

例如:

declare @SomeDate datetime = '2009-05-28 16:30:22' select trunc_date(@SomeDate) ----------------------- 2009-05-28 00:00:00.000 

这仍然经常会收集更多的选票,甚至几年后,所以我需要更新它的现代版本的Sql Server。 对于Sql Server 2008及更高版本,这很简单:

 cast(getDate() As Date) 

请注意,靠近底部的最后三段仍然适用,你经常需要退后一步,find一种方法来避免演员摆在首位。

但是还有其他方法可以做到这一点。 这是最常见的。

正确的方法(自Sql Server 2008以来新增):

 cast(getdate() As Date) 

正确的方法(旧):

 dateadd(dd, datediff(dd,0, getDate()), 0) 

现在这个年龄比较大,但是还是值得一提的,因为它也可以很容易地适应其他时间点,比如月,分,小时或者年的第一时刻。

这种正确的方法使用文档化的function,是ANSI标准的一部分,并保证工作,但可能会稍微慢一些。 它通过查找从第0天到当天有多less天,并将这些天添加到第0天。无论您的date时间如何存储以及不pipe您的语言环境如何,它都将起作用。

快速的方法:

 cast(floor(cast(getdate() as float)) as datetime) 

这是有效的,因为date时间列存储为8字节的二进制值。 将它们转换为浮动状态,将它们放置以除去小数部分,并且在将它们转换回date时间时,值的时间部分将消失。 这只是一点点转变,没有复杂的逻辑,而且速度非常快。

请注意,这依赖于实现细节,微软可以随时更改,即使在自动更新服务中也是如此。 这也不是很便携。 在实践中,这个实现不太可能很快就会改变,但是如果你select使用它,那么意识到这个危险是很重要的。 而现在我们可以select投射date,这是很less有必要的。

错误的方法:

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

错误的方式通过转换为string,截断string,并转换回date时间。 这是错误的 ,原因有两个:1)它可能不适用于所有地区,2)它是关于尽可能慢的方法来做到这一点…而不仅仅是一点; 这比其他选项慢了一两个数量级。


更新这最近得到了一些选票,所以我想补充说,自从我发布这个,我已经看到了一些非常可靠的证据,Sql Server将优化“正确”的方式和“快速”方式之间的性能差异这意味着你现在应该倾向于前者。

在这两种情况下,您都希望编写查询以避免首先执行此操作 。 你应该在数据库上做这个工作是非常罕见的。

在大多数地方,数据库已经是你的瓶颈。 一般来说,增加硬件来提高性能是最为昂贵的服务器,也是最难添加硬件的服务器(例如,您必须平衡磁盘和内存之间的关系)。 在技​​术上和从商业angular度来看,这也是最难扩展的。 在技​​术上,添加Web或应用程序服务器要比数据库服务器简单得多,即使这样做不对,您也不用为IIS或Apache支付每服务器许可证$ 20,000 +。

我试图说的是,只要有可能,你应该在应用程序级别上做这个工作。 唯一一次你应该发现自己截断Sql Server上的date时间是当你需要按日进行分组的时候,即使这样你也许应该有一个额外的列设置为一个计算列,保持在插入/更新时间,或维护在应用程序逻辑。 从数据库中获取这个索引突破,CPU繁重的工作。

仅适用于SQL Server 2008

 CAST(@SomeDateTime AS Date) 

然后如果你愿意的话,把它转换回date时间

 CAST(CAST(@SomeDateTime AS Date) As datetime) 

只是为了更完整的回答,这里有一个工作方式,截断任何date部分,包括分钟(用截断datereplaceGETDATE() )。

这不同于接受的答案,因为您不仅可以使用dd (天),而且可以使用任何date部分(请参阅此处 ):

 dateadd(minute, datediff(minute, 0, GETDATE()), 0) 

请注意,在上面的expression式中, 0是一年(1900-01-01)开始的常量date。 如果您需要截断较小的部分,例如几秒或几毫秒,则需要采用一个接近截断date的常量date以避免溢出。

我必须这样做时,我在网上find的片段是:

  dateadd(dd,0, datediff(dd,0, YOURDATE)) eg dateadd(dd,0, datediff(dd,0, getDate())) 

在SQl 2005中,trunc_date函数可以像这样写。

(1)

 CREATE FUNCTION trunc_date(@date DATETIME) RETURNS DATETIME AS BEGIN CAST(FLOOR( CAST( @date AS FLOAT ) )AS DATETIME) END 

第一种方法要干净得多。 它只使用3个方法调用,包括最终的CAST()并且不执行string连接,这是一个自动加号。 此外,这里没有大型的演员。 如果您可以想象date/时间戳可以表示,那么从date转换为数字并返回date是一个相当简单的过程。

(2)

 CREATE FUNCTION trunc_date(@date DATETIME) RETURNS DATETIME AS BEGIN SELECT CONVERT(varchar, @date,112) END 

如果你担心微软的date时间(2)或(3)的实现可能没问题。

(3)

 CREATE FUNCTION trunc_date(@date DATETIME) RETURNS DATETIME AS BEGIN SELECT CAST((STR( YEAR( @date ) ) + '/' +STR( MONTH( @date ) ) + '/' +STR( DAY(@date ) ) ) AS DATETIME END 

第三,比较详细的方法。 这需要将date分成年,月和日,将它们放在“yyyy / mm / dd”格式中,然后再将其转换回date。 这个方法涉及7个方法调用,包括最终的CAST(),更不用说string连接了。

 CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP) 

你可以这样做(SQL 2008):

declare @SomeDate date = getdate()

 select @SomeDate 

2009-05-28

selectcast(floor(cast(getdate()as float))作为date时间)参考: http : //microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql-server.html

对于那些来到这里寻找将DATETIME字段截断为不到一整天的方法,例如每分钟都可以使用这个:

 SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) + (FLOOR((CAST(GETDATE() AS FLOAT) - FLOOR(CAST(GETDATE() AS FLOAT))) * 1440.0) + (3.0/86400000.0)) / 1440.0 AS DATETIME) 

所以如果今天是2010-11-26 14:54:43.123那么这将会在2010-11-26 14:54:00.000返回。

要更改它所在的时间间隔,请将1440.0replace为一天中的时间间隔数,例如:

 24hrs = 24.0 (for every hour) 24hrs / 0.5hrs = 48.0 (for every half hour) 24hrs / (1/60) = 1440.0 (for every minute) 

(总是把一个.0结尾隐式地转换成一个浮点数。)


对于那些想知道(3.0/86400000)在我的计算中是什么的人来说,SQL Server 2005似乎不能准确地从FLOATDATETIME ,所以在铺设它之前增加了3毫秒。

这个查询应该给你相当于Oracle中trunc(sysdate)结果。

 SELECT * FROM your_table WHERE CONVERT(varchar(12), your_column_name, 101) = CONVERT(varchar(12), GETDATE(), 101) 

希望这可以帮助!

你也可以using Substring从date时间variables的using Substring提取date,并且回到date时间将忽略时间部分。

 declare @SomeDate datetime = '2009-05-28 16:30:22' SELECT cast(substring(convert(varchar(12),@SomeDate,111),0,12) as Datetime) 

另外,你可以访问datetimevariables的一部分,并将它们合并到构造截断date,如下所示:

 SELECT cast(DATENAME(year, @Somedate) + '-' + Convert(varchar(2),DATEPART(month, @Somedate)) + '-' + DATENAME(day, @Somedate) as datetime) 

甲骨文:

 TRUNC(SYSDATE, 'MONTH') 

SQL Server:

 DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField) 

可以同样用于从date截断分钟或小时。

TRUNC(aDate,'DD')将截断min,sec和hrs

SRC: http : //www.techonthenet.com/oracle/functions/trunc_date.php