在SQL Server中截断日期的最佳方法是什么?

zu0ti5jz  于 2022-10-22  发布在  SQL Server
关注(0)|答案(6)|浏览(226)

如果我有2010-03-01 17:34:12.018这样的日期值
将此转换为2010-03-01 00:00:00.000的最有效方法是什么?
第二个问题是,模拟Oracle的TRUNC函数的最佳方法是什么,该函数允许您在年、季度、月、周、日、小时、分钟和秒边界进行截断?

6ie5vjzr

6ie5vjzr1#

要舍入到最近的全天,有三种方法广泛使用。第一个使用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)

这也适用于一刻半小时。

thtygnil

thtygnil2#

如果您使用的是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)
lmvvr0a8

lmvvr0a83#

尝试:

SELECT DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)

**更新:**第二个问题的答案:多年来,你可以使用我的答案的一个稍微修改的版本:

SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)

季度:

SELECT DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)

等等
我检查了几分钟,没关系。但几秒钟后,我收到一条溢出消息:
两个日期时间列的差异导致运行时溢出。

**另一个更新:**请查看同一问题的以下答案

r6hnlfcb

r6hnlfcb4#

这很晚了,但会产生帖子中要求的准确结果。我也觉得它比使用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
日期时间:2010-03-01 17:34:12.017

pbossiut

pbossiut5#

不确定这是否是最有效的,但我喜欢在@SomeDate是您的字段的情况下使用下面的简单性。

Concat(Year(@SomeDate), '-', Month(@SomeDate), '-', '01')
nbewdwxp

nbewdwxp6#

如果您想以独立于SET DATEFIRST的方式将日期截断到周开始,您可以:

--change a date backwards to nearest Monday
DATEADD(DAY, (DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)-7)%7, YOUR_COLUMN)

细分如下:

  • DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN):已知星期一(2001-01-01是星期一)的dw减去你的日期的m1o3p,有效地给出了“你的日期和星期一之间的天数差”或“我们要把你的日期滚动到星期一还要多少天”
  • ( ... -7)%7-我们从中减去7,并将结果乘以7。
  • 我们这样做是因为,如果DATEFIRST是7(星期日),而您的日期列是星期日,那么您的dw就是1,而您已知的星期一是2
  • 这意味着dw_for_known_monday - dw_for_your_date的结果是+1而不是-6
  • 这意味着DATEADD会将您的日期向前滚动到下一个星期一,而不是向后滚动到前一个星期
  • 如果我们从中减去7,那么结果肯定是负数,但我们不希望你的周一(与已知的周一不同0天)以-7DATEADD结束,因此我们将结果乘以7。
  • 这会将任何有问题的-7转换为0,这意味着DATEADD只会在-60之间有一个“天数”参数
  • DATEADD(DAY, (DATEPART(dw, '2001-01-01') - DATEPART(dw, YOUR_COLUMN)-7)%7, YOUR_COLUMN)-然后我们用DATEADD计算上述步骤中的(负)天数

如果你想把日期倒转到星期天,那么把日期2001-01-01改为已知的星期天(如2000-12-31),等等

相关问题