SQL中的Datediff之争

SQL中的Datediff之争,sql,datediff,Sql,Datediff,我正在用SQL编写一个小查询,并与一个似乎有人以前遇到过的问题发生了冲突。我试图找出两个日期之间的月数。我用了一个像 DATEDIFF(m,{firstdate},{seconddate}) 然而,我注意到这个函数正在统计日期超过每月阈值的时间。例如 DATEDIFF(m,3/31/2011,4/1/2011) will yield 1 DATEDIFF(m,4/1/2011,4/30/2011) will yield 0 DATEDIFF(m,3/1/2011,4/30/2011) w

我正在用SQL编写一个小查询,并与一个似乎有人以前遇到过的问题发生了冲突。我试图找出两个日期之间的月数。我用了一个像

DATEDIFF(m,{firstdate},{seconddate})
然而,我注意到这个函数正在统计日期超过每月阈值的时间。例如

DATEDIFF(m,3/31/2011,4/1/2011) will yield 1  
DATEDIFF(m,4/1/2011,4/30/2011) will yield 0 
DATEDIFF(m,3/1/2011,4/30/2011) will yield 1

有人知道如何计算两个日期之间的月份吗?更确切地说,是基于经过的时间,而不是通过每月阈值的次数来计算的?

如果你想计算一些概念上的月份数,为什么不计算天数的差,然后除以30,根据需要浮动。或者30.5-ish——取决于你想如何处理全年的可变月长。但在你的特殊情况下,这可能不是一个因素

以下语句具有相同的起始日期和结束日期。这些日期是相邻的,在时间上相差.000000 1秒。每条语句中的startdate和endDate之间的差异跨越其datepart的一个日历或时间边界。每个语句返回1。。。 选择DATEDIFFmonth,“2005-12-3123:59:59.999999” , '2006-01-01 00:00:00.0000000'; ....


从,部分日期部分边界。如果您对它不满意,您可能需要按照martin clayton的建议使用天作为单位

DATEDIFF是这样设计的。当评估一个特定的时间度量值(如月、日等)时,它只考虑该度量值和较高的值,而忽略较小的值。在任何时间测量中,您都会遇到这种行为。例如,如果您使用DATEDIFF来计算天数,并且一个日期在午夜前几秒,另一个日期在午夜后几秒,您将得到1天的差异,即使这两个日期仅相隔几秒

DATEDIFF旨在粗略回答以下问题:

问题:你几岁了? 回答:一些整数。你不会说我59岁4个月17天5小时35分27秒大。你说我59岁。这也是DATEDIFF的方法


如果你想要一个符合上下文含义的答案,比如你儿子说我不是8岁!我八岁四分之三!,或者我快9岁了!,然后,您应该查看下一个最小的测量值,并使用它进行近似计算。所以,如果你要在几个月后,那么就改为在几天或几小时内做一次DATEDIFF,并试着估计几个月,但它似乎与你的情况最相关,也许你想要像1-1/2个月或1.2个月之类的答案。使用CASE/if-then之类的逻辑。

有趣的是,我从来没有注意到它会这样做。一个月有多少天?考虑到日期对2011-03-15、2011-04-14、2011-03-15、2011-04-15、2011-03-15、2011-04-16、2011-01-28、2011-02-28、2011-01-28、2011-03-01、2012-01-29、2012-02-28、2012-01-29、2012-02-29、2012-01-29、2012-03-01、2012-01-30、2012-02-29、2012-03-01等等,你想要什么答案。在闰年和非闰年中,人们倾向于关注2月底左右的日期,但在其他月末日期,如2011-05-31、2011-06-30,也会出现类似的问题。最初的日期为>而你的日期为>=,这意味着如果日数相等,DATEDIFF的结果仍将减少1。另一件事是,计算2011-03-31和2011-06-30之间的月差。此方法将返回2,因为31确实大于30。但是,6月份的天数不能超过30天。在这种情况下2个月可以吗?很好。在这种情况下,这并不过分关键,但在某些情况下,它可能是你在12月和今天的1月满32岁,你不会说你是33岁。“然而,我会说你是。”安德烈——这只是一个粗俗的例子。关键是,它没有被打破——它只是被设计来给出粗略的答案。无论你使用什么测量方法,它都有1的正负误差范围。是的,我同意,它是按照设计的方式工作的。我同意DATEDIFF和people都倾向于用一个近似整数粗略地回答问题,这是一个共同点。只是DATEDIFF总是使用相同的规则,而人们不这么做。有时我们四舍五入,比如五点二十分,实际上只有十八个,而在其他时候,我们倾向于报告完整的单位数,没有任何四舍五入,就像年龄以年为单位一样。我认为OP想要的是后者,一种不需要四舍五入就能得到一个整数的方法。
DATEDIFF(m,{firstdate},ISNULL({seconddate},GETDATE())) - CASE 
                                                         WHEN DATEPART(d,{firstdate}) >= DATEPART(d,ISNULL({seconddate},GETDATE()))
                                                         THEN 1
                                                         ELSE 0