在SQL Server 2008中截断日期时间值(删除小时分钟和秒)的最佳方法是什么?
例如:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
答案 0 :(得分:457)
这仍然经常收集额外的投票,甚至几年后,所以我需要为现代版本的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天。无论您的日期时间如何存储,无论您的语言环境如何,它都能正常工作。
快捷方式:
cast(floor(cast(getdate() as float)) as datetime)
这是有效的,因为datetime列存储为8字节的二进制值。将它们转换为浮动,将它们放置以移除分数,并且当您将它们转换回日期时间时,值的时间部分将消失。它只是位移,没有复杂的逻辑,而且非常快。
请注意,这取决于实施细节Microsoft可以随时更改,即使在自动服务更新中也是如此。它也不是很便携。在实践中,这种实施很可能不会很快改变,但是如果你选择使用它,那么了解危险仍然很重要。现在我们可以选择将其作为约会,但这很少是必要的。
错误的方式:
cast(convert(char(11), getdate(), 113) as datetime)
错误的方法是转换为字符串,截断字符串,然后转换回日期时间。这是错误的,原因有两个:1)它可能无法在所有语言环境中运行; 2)它是最慢的可能方式...而不仅仅是一点点;它比其他选项慢一个数量级或两个数量级。
更新这最近得到了一些投票,所以我想补充说,自从我发布这个以来,我已经看到一些非常可靠的证据表明Sql Server将优化它们之间的性能差异“正确”的方式和“快速”的方式,意味着你现在应该支持前者。
在任何一种情况下,您都希望编写查询以避免首先需要执行此操作。你应该在数据库上做这项工作是非常罕见的。
在大多数地方,数据库已经成为你的瓶颈。通常,服务器是增加硬件以提高性能的最昂贵的服务器,也是最难获得正确添加硬件的服务器(例如,您必须平衡磁盘与内存)。从技术角度和商业角度来看,它也是最难扩展的;在技术上添加Web或应用程序服务器比数据库服务器更容易,即使这是假的,您也不需要为IIS或Apache支付每服务器许可证20,000美元。
我想说的是,只要有可能,你应该在应用程序级别完成这项工作。您应该在Sql Server上截断日期时间的仅时间是您需要按日分组的时间,即使这样,您可能应该将额外的列设置为计算列,并保持在插入/更新时间,或在应用程序逻辑中维护。从数据库中获取这个索引破解,cpu繁重的工作。
答案 1 :(得分:44)
仅限SQL Server 2008
CAST(@SomeDateTime AS Date)
如果你想要
,那就把它扔回日期时间CAST(CAST(@SomeDateTime AS Date) As datetime)
答案 2 :(得分:20)
为了更完整的答案,这里有一个截断日期部分的工作方式,包括分钟(将GETDATE()
替换为截断日期)。
这与接受的答案不同,您不仅可以使用dd
(天),还可以使用任何日期部分(请参阅here):
dateadd(minute, datediff(minute, 0, GETDATE()), 0)
请注意,在上面的表达式中,0
是一年开始时的常量日期(1900-01-01)。如果需要截断到较小的部分,例如秒或毫秒,则需要采用一个更接近截断日期的常量日期,以避免溢出。
答案 3 :(得分:7)
我必须这样做时在网上找到的片段是:
dateadd(dd,0, datediff(dd,0, YOURDATE))
e.g.
dateadd(dd,0, datediff(dd,0, getDate()))
答案 4 :(得分:1)
在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(),并且不执行字符串连接,这是一个自动加号。此外,这里没有巨大的类型演员。如果您可以想象可以表示日期/时间戳,那么从日期转换为数字并返回日期是一个相当简单的过程。
(2)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CONVERT(varchar, @date,112)
END
如果您担心微软的日期时间(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
第三,更详细的方法。这需要将日期分为年,月和日部分,将它们以“yyyy / mm / dd”格式组合在一起,然后将其转换回日期。此方法涉及7个方法调用,包括最终的CAST(),更不用说字符串连接。
答案 5 :(得分:1)
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)
答案 6 :(得分:0)
对于那些来到这里寻找将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毫秒地板吧。
答案 7 :(得分:0)
选择cast(floor(cast(getdate()as float))作为datetime) 参考:http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql-server.html
答案 8 :(得分:0)
此查询应该为您提供相当于Oracle中trunc(sysdate)
的结果。
SELECT *
FROM your_table
WHERE CONVERT(varchar(12), your_column_name, 101)
= CONVERT(varchar(12), GETDATE(), 101)
希望这有帮助!
答案 9 :(得分:0)
Oracle:
TRUNC(SYSDATE, 'MONTH')
SQL Server:
DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField)
可以类似地用于截断日期的分钟或小时。
答案 10 :(得分:0)
你可以这样做(SQL 2008):
声明@SomeDate date = getdate()
select @SomeDate
2009-05-28
答案 11 :(得分:0)
在使用分析时,您可能经常需要日期\时间截断。所以我做了一个小函数来帮助解决这个问题:
CREATE FUNCTION TRUNC_DATE
(
@datetime datetime, -- datetime to be truncated
@level VARCHAR(10) -- truncation level: year, month, day, hour and minute
)
RETURNS DATETIME
AS
BEGIN
IF (UPPER(@level) = 'YEAR')
RETURN DATEADD(YEAR, DATEDIFF(YEAR, 0, @datetime), 0)
ELSE IF (UPPER(@level) = 'MONTH')
RETURN DATEADD(MONTH, DATEDIFF(MONTH, 0, @datetime), 0)
ELSE IF(UPPER(@level) = 'DAY')
RETURN DATEADD(DAY, DATEDIFF(DAY, 0, @datetime), 0)
ELSE IF (UPPER(@level) = 'HOUR')
RETURN DATEADD(HOUR, DATEDIFF(HOUR, 0, @datetime), 0)
ELSE IF (UPPER(@level) = 'MINUTE')
RETURN DATEADD(MINUTE, DATEDIFF(MINUTE, 0, @datetime), 0)
RETURN @datetime
END
GO
要评估函数(使用您的列更改 GETDATE()):
SELECT DBO.TRUNC_DATE(GETDATE(), 'YEAR') YEAR;
SELECT DBO.TRUNC_DATE(GETDATE(), 'MONTH') YEAR_MONTH;
SELECT DBO.TRUNC_DATE(GETDATE(), 'DAY') YEAR_MONTH_DAY;
SELECT DBO.TRUNC_DATE(GETDATE(), 'HOUR') YEAR_MONTH_DAY_HOUR;
SELECT DBO.TRUNC_DATE(GETDATE(), 'MINUTE') YEAR_MONTH_DAY_HOUR_MINUTE;
输出:
答案 12 :(得分:-1)
TRUNC(aDate,'DD')将截断min,sec和hrs
SRC:http://www.techonthenet.com/oracle/functions/trunc_date.php