使用T-SQL DATEADD和DATEDIFF函数

时间:2013-05-15 20:40:12

标签: sql-server-2008 tsql

我试图理解在计算日期时有人错误地执行以下要求的代码:

派生的JE_ACCTNG_DT设置为等于创建和发送Feed时当前年份的前一个月的最后一天。
例如,如果当前年份是2013年,则JE_ACCTNG_DT将根据发送订阅源的季度进行以下操作:

  • JE_ACCTNG_DT = 2013年3月31日2013年4月1日发送的第一季度供稿
  • JE_ACCTNG_DT = 2013年6月30日2013年7月1日发送的第二季度供稿
  • JE_ACCTNG_DT = 2013年9月30日2013年10月1日发送的第三季度供稿
  • JE_ACCTNG_DT = 12/31/2013 2014年1月1日发送的第四季度供稿

我看到有人实现了这样的代码,如果将日期时间结果转换为日期数据类型(时间部分被删除),它似乎给出了需求中给出的示例的正确答案

DECLARE @FEED_DT datetime 

SET @FEED_DT = '4/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@FEED_DT),0))


SET @FEED_DT = '7/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@FEED_DT),0))
--2013-06-30 23:59:59.000

SET @FEED_DT = '10/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@FEED_DT),0))
--2013-09-30 23:59:59.000


SET @FEED_DT = '1/1/2014'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@FEED_DT),0))
--2013-09-30 23:59:59.000

令我困惑的是DATEDIFF函数接受以下参数:datepart和两个日期

DATEDIFF(datepart,startdate,enddate)

如果您注意到上述情况,则代码会将日期部分设置为“m”,但在预期日期时将第二个参数传递为零。

DECLARE @FEED_DT datetime = '4/1/2013'
DECLARE @DateAddResult as int 

SET @DateAddResult = DATEDIFF(m,0,@FEED_DT)
select @DateAddResult 
--1359
select DATEADD(s,-1,DATEADD(mm, @DateAddResult,0))
--2013-03-31 23:59:59.000

代码到底在做什么?我会预料到一个错误。它是否将0值强制转换为日期?

我认为要求的真正要点是计算上一季度的最后一天。我就是这样做的。

SELECT dateadd(day, -1, DATEADD(quarter,DATEDIFF(quarter,'1900/01/01', GETDATE()), '1900/01/01')) as FirstDayOfQuarter

2 个答案:

答案 0 :(得分:2)

鉴于此:

select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@FEED_DT),0)

让我们一次拿一件......

DATEDIFF(m,0,@FEED_DT)

...计算从日期值零(评估为1-1-1900)到日期时间字段@FEED_DT中开始的日期值的整数整数月数。假设这个值是@ElapsedMonthsSinceZero并将此变量替换为原始的嵌套函数,给出:

选择DATEADD(s,-1,DATEADD(mm,@ ElapsedMonthsSinceZero,0))

现在让我们评估一下这个部分:

DATEADD(mm, @ElapsedMonthsSinceZero,0)

这会将相同的月份添加到日期“零”,即1-1-1900,这会将您带到@FEED_DT日期的第一天。基本上,我们到目前为止所做的是计算从日期0开始经过的整个月数,从第1天到月份之间的任何一天都被截断。这给了我们@FirstDayOfFEED_DT。将其替换为函数给我们......

select DATEADD(s,-1,@FirstDayOfFEED_DT)

现在我们有了@FEED_DT日期的第一天,减去1给了我们上一个月的最后一天。

我想我只是因为传递了0而不是日期的差异而被抛弃了。

答案 1 :(得分:1)

假设您在新列中添加了几天,并且您有一个参数@date的存储过程,并且您希望将当前日期添加到该参数并以天为单位获取结果。

 DateAdd(days,@date,Getdate())