在SQL Server中,如何将DATETIME“降低”到第二/分钟/小时/日/年?
假设我的日期 2008-09-17 12:56:53.430 ,那么地板的输出应该是:
答案 0 :(得分:95)
关键是使用DATEADD和DATEDIFF以及相应的SQL timespan枚举。
declare @datetime datetime;
set @datetime = getdate();
select @datetime;
select dateadd(year,datediff(year,0,@datetime),0);
select dateadd(month,datediff(month,0,@datetime),0);
select dateadd(day,datediff(day,0,@datetime),0);
select dateadd(hour,datediff(hour,0,@datetime),0);
select dateadd(minute,datediff(minute,0,@datetime),0);
select dateadd(second,datediff(second,'2000-01-01',@datetime),'2000-01-01');
select dateadd(week,datediff(week,0,@datetime),-1); --Beginning of week is Sunday
select dateadd(week,datediff(week,0,@datetime),0); --Beginning of week is Monday
请注意,当你在第二层铺设地板时,如果你使用0,你经常会得到算术溢出。所以选择一个已知的值,保证低于你试图放置的日期时间。
答案 1 :(得分:28)
在SQL Server中,这是一个小技巧:
SELECT CAST(FLOOR(CAST(CURRENT_TIMESTAMP AS float)) AS DATETIME)
您将DateTime转换为float,它将Date表示为整数部分,将Time表示为传递的一天的分数。砍掉那个小数部分,然后把它转回DateTime,然后你就在那天开始时午夜。
这可能比所有DATEADD和DATEDIFF更有效。输入肯定更容易。
答案 2 :(得分:11)
扩展Convert / Cast解决方案,在Microsoft SQL Server 2008中,您可以执行以下操作:
cast(cast(getdate() as date) as datetime)
只需将getdate()
替换为日期时间的任何列。
此转换不涉及任何字符串。
这适用于即席查询或更新,但对于密钥连接或频繁使用的处理,最好在处理过程中处理转换或重新定义表以获得适当的密钥和数据。
2005年,您可以使用更加简洁的楼层:cast(floor(cast(getdate() as float)) as datetime)
我认为这也不会使用字符串转换,但我不能说比较实际效率与扶手椅估算值。
答案 3 :(得分:6)
多年来,我多次使用@Portman's answer作为参考资料,并将其工作转移到您可能觉得有用的功能中。
我没有声明其性能,只是将其作为用户的工具提供。
我问,如果您决定对此答案进行投票,请同时提出@Portman's answer,因为我的代码是他的衍生产品。
IF OBJECT_ID('fn_FloorDate') IS NOT NULL DROP FUNCTION fn_FloorDate
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fn_FloorDate] (
@Date DATETIME = NULL,
@DatePart VARCHAR(6) = 'day'
)
RETURNS DATETIME
AS
BEGIN
IF (@Date IS NULL)
SET @Date = GETDATE();
RETURN
CASE
WHEN LOWER(@DatePart) = 'year' THEN DATEADD(YEAR, DATEDIFF(YEAR, 0, @Date), 0)
WHEN LOWER(@DatePart) = 'month' THEN DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0)
WHEN LOWER(@DatePart) = 'day' THEN DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
WHEN LOWER(@DatePart) = 'hour' THEN DATEADD(HOUR, DATEDIFF(HOUR, 0, @Date), 0)
WHEN LOWER(@DatePart) = 'minute' THEN DATEADD(MINUTE, DATEDIFF(MINUTE, 0, @Date), 0)
WHEN LOWER(@DatePart) = 'second' THEN DATEADD(SECOND, DATEDIFF(SECOND, '2000-01-01', @Date), '2000-01-01')
ELSE DATEADD(DAY, DATEDIFF(DAY, 0, @Date), 0)
END;
END
<强>用法:强>
DECLARE @date DATETIME;
SET @date = '2008-09-17 12:56:53.430';
SELECT
@date AS [Now],--2008-09-17 12:56:53.430
dbo.fn_FloorDate(@date, 'year') AS [Year],--2008-01-01 00:00:00.000
dbo.fn_FloorDate(default, default) AS [NoParams],--2013-11-05 00:00:00.000
dbo.fn_FloorDate(@date, default) AS [ShouldBeDay],--2008-09-17 00:00:00.000
dbo.fn_FloorDate(@date, 'month') AS [Month],--2008-09-01 00:00:00.000
dbo.fn_FloorDate(@date, 'day') AS [Day],--2008-09-17 00:00:00.000
dbo.fn_FloorDate(@date, 'hour') AS [Hour],--2008-09-17 12:00:00.000
dbo.fn_FloorDate(@date, 'minute') AS [Minute],--2008-09-17 12:56:00.000
dbo.fn_FloorDate(@date, 'second') AS [Second];--2008-09-17 12:56:53.000
答案 4 :(得分:2)
CONVERT()函数也可以执行此操作,具体取决于您使用的样式。
答案 5 :(得分:1)
太糟糕了,它不是Oracle,否则你可以使用trunc()或to_char()。
但是我遇到了与SQL Server类似的问题并使用了CONVERT()和DateDiff()方法,引用为here
答案 6 :(得分:0)
有几种方法可以给这只猫皮肤涂抹=)
select convert(datetime,convert(varchar,CURRENT_TIMESTAMP,101))
答案 7 :(得分:0)
DateAdd和DateDiff可以帮助完成许多不同的任务。例如,您可以找到任何月份的最后一天,也可以找到上个月或下个月的最后一天。
----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth
答案 8 :(得分:-2)
由于PostgreSQL也是一个“SQL Server”,我会提到
date_trunc()
这正是你正在优雅地问的。
例如:
select date_trunc('hour',current_timestamp); date_trunc ------------------------ 2009-02-18 07:00:00-08 (1 row)