如果我的日期值类似2010-03-01 17:34:12.018
将此转换为2010-03-01 00:00:00.000
的最有效方法是什么?
作为第二个问题,模拟Oracle TRUNC
函数的最佳方法是什么,这将允许您截断年,季度,月,周,日,小时,分钟和第二边界?
答案 0 :(得分:31)
要舍入到最近的整天,有三种方法可供广泛使用。第一个使用datediff
来查找自0
日期时间以来的天数。 0
日期时间对应于1900年1月1日。通过将日差添加到开始日期,您已整理到一整天;
select dateadd(d, 0, datediff(d, 0, getdate()))
第二种方法是基于文本的:它使用varchar(10)
截断文本描述,只留下日期部分:
select convert(varchar(10),getdate(),111)
第三种方法使用的事实是datetime
实际上是一个浮点,表示自1900年以来的天数。因此,通过将其舍入为整数,例如使用floor
,您将得到一天的开始:
select cast(floor(cast(getdate() as float)) as datetime)
要回答第二个问题,一周的开始比较棘手。一种方法是减去星期几:
select dateadd(dd, 1 - datepart(dw, getdate()), getdate())
这也返回一个时间部分,因此你必须将它与一个时间剥离方法结合起来才能到达第一个日期。例如,@start_of_day
作为可读性的变量:
declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(dd, 1 - datepart(dw, @start_of_day), @start_of_day)
年,月,小时和分钟的开始仍然适用于“自1900年以来的差异”方法:
select dateadd(yy, datediff(yy, 0, getdate()), 0)
select dateadd(m, datediff(m, 0, getdate()), 0)
select dateadd(hh, datediff(hh, 0, getdate()), 0)
select dateadd(mi, datediff(mi, 0, getdate()), 0)
舍入第二个需要采用不同的方法,因为0
以来的秒数会导致溢出。一种方法是使用当天的开头而不是1900作为参考日期:
declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(s, datediff(s, @start_of_day, getdate()), @start_of_day)
要舍入5分钟,请调整分钟舍入方法。取微小差异的商,例如使用/5*5
:
select dateadd(mi, datediff(mi,0,getdate())/5*5, 0)
这也适用于四分之一小时。
答案 1 :(得分:15)
如果您使用的是SQL Server 2008,则可以使用新的Date
数据类型,如下所示:
select cast(getdate() as date)
如果您仍然需要将值设置为DateTime
数据类型,则可以执行以下操作:
select cast(cast(getdate() as date) as datetime)
应该适用于所有SQL Server版本的方法是:
select cast(floor(cast(getdate() as float)) as datetime)
答案 2 :(得分:2)
尝试:
SELECT DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
更新:回答第二个问题: 多年来你可以使用我的答案的一点点修改版本:
SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
季度:
SELECT DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)
等等。
我检查了几分钟 - 没关系。但是几秒钟我就收到了溢出信息:
两个日期时间列的差异 在运行时导致溢出。
还有一次更新:查看同一question
的以下答案答案 3 :(得分:2)
这已经很晚了,但会产生帖子中要求的确切结果。我也觉得它比使用dateadd更直观,但这是我的偏好。
declare @SomeDate datetime = '2010-03-01 17:34:12.018'
SELECT
DATEFROMPARTS(
YEAR(@SomeDate)
,MONTH(@SomeDate)
,'01'
) AS CUR_DATE_FROM_PARTS
,DATETIMEFROMPARTS(
YEAR(@SomeDate)
,MONTH(@SomeDate)
,'01' --DAY(@SomeDate)
,'00' --DATEPART(HOUR,@SomeDate)
,'00' --DATEPART(MINUTE,@SomeDate)
,'00' --DATEPART(SECOND,@SomeDate)
,'00' --DATEPART(MILLISECOND,@SomeDate)
) AS CUR_DATETIME_FROM_PARTS
,@SomeDate AS CUR_DATETIME
,YEAR(@SomeDate) AS CUR_YEAR
,MONTH(@SomeDate) AS CUR_MONTH
,DAY(@SomeDate) AS CUR_DAY
,DATEPART(HOUR,@SomeDate) AS CUR_HOUR
,DATEPART(MINUTE,@SomeDate) AS CUR_MINUTE
,DATEPART(SECOND,@SomeDate) AS CUR_SECOND
,DATEPART(MILLISECOND,@SomeDate) AS CUR_MILLISECOND
FROM Your_Table
截断日期:2010-03-01
截断日期时间:2010-03-01 00:00:00.000
DateTime:2010-03-01 17:34:12.017
答案 4 :(得分:0)
不确定这是否是最有效的方法,但我喜欢使用以下简单方法,其中@SomeDate是您的字段。
Concat(Year(@SomeDate), '-', Month(@SomeDate), '-', '01')