在SQL Server 2008中截断日期时间值(如删除小时、分钟和秒)的最佳方法是什么?

例如:

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

-----------------------
2009-05-28 00:00:00.000

当前回答

SQL Server 2022有DATETRUNC

DECLARE @d datetime2 = '2021-12-08 11:30:15.1234567';
SELECT 'Year', DATETRUNC(year, @d);
SELECT 'Quarter', DATETRUNC(quarter, @d);
SELECT 'Month', DATETRUNC(month, @d);
SELECT 'Week', DATETRUNC(week, @d); -- Using the default DATEFIRST setting value of 7 (U.S. English)
SELECT 'Iso_week', DATETRUNC(iso_week, @d);
SELECT 'DayOfYear', DATETRUNC(dayofyear, @d);
SELECT 'Day', DATETRUNC(day, @d);
SELECT 'Hour', DATETRUNC(hour, @d);
SELECT 'Minute', DATETRUNC(minute, @d);
SELECT 'Second', DATETRUNC(second, @d);
SELECT 'Millisecond', DATETRUNC(millisecond, @d);
SELECT 'Microsecond', DATETRUNC(microsecond, @d);
Year        2021-01-01 00:00:00.0000000
Quarter     2021-10-01 00:00:00.0000000
Month       2021-12-01 00:00:00.0000000
Week        2021-12-05 00:00:00.0000000
Iso_week    2021-12-06 00:00:00.0000000
DayOfYear   2021-12-08 00:00:00.0000000
Day         2021-12-08 00:00:00.0000000
Hour        2021-12-08 11:00:00.0000000
Minute      2021-12-08 11:30:00.0000000
Second      2021-12-08 11:30:15.0000000
Millisecond 2021-12-08 11:30:15.1230000
Microsecond 2021-12-08 11:30:15.1234560

https://learn.microsoft.com/en-us/sql/t-sql/functions/datetrunc-transact-sql?view=sql-server-ver16

其他回答

对于那些来到这里寻找一种方法来截断一个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.0替换为一天中的间隔数,例如:

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似乎并没有准确地从FLOAT转换为DATETIME,所以这增加了3毫秒。

当我不得不这样做时,我在网上找到的片段是:

 dateadd(dd,0, datediff(dd,0, YOURDATE))
 e.g.
 dateadd(dd,0, datediff(dd,0, getDate()))

这继续频繁地收集额外的投票,甚至几年后,所以我需要更新它的现代版本的Sql Server。对于Sql Server 2008及以后的版本,它很简单:

cast(getDate() As Date)

请注意,接近底部的最后三段仍然适用,您通常需要后退一步,找到一种在一开始就避免强制转换的方法。

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

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

cast(getdate() As Date)

正确的方式(旧):

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

它现在已经很老了,但仍然值得了解,因为它也可以很容易地适应其他时间点,比如每月、分钟、小时或年的第一个时刻。

这种正确的方法使用ansi标准中有文档的函数,这些函数保证可以工作,但可能会稍慢一些。它的工作原理是找出从第0天到今天有多少天,然后把这些天加到第0天。无论您的datetime是如何存储的,无论您的语言环境是什么,它都将工作。

最快捷的方法:

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

这是因为datetime列存储为8字节二进制值。将它们强制转换为浮动,将它们向下转换以删除分数,当您将值强制转换回datetime时,值的时间部分将消失。它只是位移位,没有复杂的逻辑,而且非常快。

请注意,这依赖于微软可以随时更改的实现细节,即使是在自动服务更新中。它也不是很便携。在实践中,这种实现不太可能很快改变,但如果您选择使用它,那么意识到其中的危险仍然很重要。既然我们可以选择约会,那就没什么必要了。

错误的方式:

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

错误的工作方式是转换为字符串,截断字符串,然后转换回日期时间。这是错误的,有两个原因:1)它可能不能在所有地区工作,2)这是最慢的方式……而且不是一点点;它比其他选项慢了一两个数量级。


这最近得到了一些投票,所以我想补充一点,自从我发布了这篇文章以来,我已经看到了一些非常确凿的证据,Sql Server将优化“正确”方式和“快速”方式之间的性能差异,这意味着你现在应该支持前者。

在这两种情况下,您都希望编写查询以避免在一开始就需要这样做。在数据库上执行此工作的情况非常少。

In most places, the database is already your bottleneck. It's generally the server that's the most expensive to add hardware to for performance improvements and the hardest one to get those additions right (you have to balance disks with memory, for example). It's also the hardest to scale outward, both technically and from a business standpoint; it's much easier technically to add a web or application server than a database server and even if that were false you don't pay $20,000+ per server license for IIS or apache.

我试图说明的观点是,只要有可能,您就应该在应用程序级别上完成这项工作。在Sql Server上,你只会在需要按天分组时截断datetime,即使这样,你也应该将一个额外的列设置为计算列,在插入/更新时维护,或者在应用程序逻辑中维护。从数据库中删除这种破坏索引、cpu负荷大的工作。

仅适用于SQL Server 2008

CAST(@SomeDateTime AS Date) 

然后将其转换回datetime

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

TRUNC(aDate, 'DD')将截断分钟,秒和小时

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