2013-06-27 56 views
-4

我想问3个关于下面的代码的问题(请原谅冗长的代码清单,我希望这些代码能够提供足够的上下文)。存储过程中的SQL Server日期计算

请注意,这里的代码取决于它执行的日期。出于这个原因,我的问题涉及到一个假设的情况有两种不同的执行日期:

  1. 2014年3月1日
  2. 2014年1月1日

我的问题是在我上的这一些地区的理解是否正确的,即:

A。该SELECT DATEADD表达式(第1行)将:

  • 2014年3月1日创建的日期时间2014-02-31 23:59:59

。上线码6-9将:

  • 2014年3月1日创建日期时间2014-02-01 00:00:00
  • 2014年1月1日创建日期时间2013-02-01 00:00:00

C。上线11-14的代码将:

  • 2014年3月1日创建日期时间2015-01-30 00:00:00
  • 2014年1月1日创建日期时间2014-01-30 00:00:00

这是理解是否正确?

1. SET @ldpmth = (SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))) 
2. SET @yr = (SELECT YEAR(@ldpmth)) 
3. SET @mth = 0 
4. SET @dy = 0 
5. 
6. SET @fysdate = (SELECT CASE WHEN MONTH(@ldpmth) >= 2 THEN 
7. DATEADD(MM, 1,CAST(CAST(@[email protected][email protected] AS NVARCHAR(50)) AS DATETIME)) 
8. ELSE DATEADD(MM, 1, CAST(CAST((@yr-1)[email protected][email protected] AS NVARCHAR(50)) 
9. AS DATETIME)) END) 
10. 
11. SET @fyedate = (SELECT CASE WHEN MONTH(@ldpmth) >= 2 THEN 
12. DATEADD(YY, 1, CAST(CAST(@[email protected][email protected] AS NVARCHAR(50)) AS DATETIME)) + 30 
13. ELSE DATEADD(YY, 1, CAST(CAST((@yr-1)[email protected][email protected] AS NVARCHAR(50)) 
14. AS DATETIME)) + 30 END) 

(谢谢所有谁迄今回答了。其实,这是在我工作的地方,几年前开发的(但没有记录)代码,我一直负责其转换为一个可行的形式客户端使用Crystal Reports)

+1

为什么不能用'2014-03-01'代替'GETDATE()'并自己测试它们? – Kermit

+0

对于问题A,你做错了。你可能试图捕获上个月发生的所有事情,并且你正在努力计算一个包容性的端点(目前排除了发生在那天的最后一分钟x毫秒内的任何事情) - 计算起来要容易得多当你处理连续时,一个*独占*上限。 –

回答

2

自2014年3月1日创建日期时间2014年2月31日23:59:59

号AFAIK,没有任何DBMS这是如此愚蠢,它认为2月31日是一个交流两个日期。第1行的SQL语句将返回值'Feb 28 2014 23:59:59'。

您可以将实际日期替换为GETDATE()和猜测来测试您的所有语句。在第一个查询,例如,使用

SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0)); 
               ^^^^^^^^^^ 

你或许可以在本地运行一个版本的SQL Server。 SQL Server 2008甚至安装在Windows XP上。如果你不能忍受,那么总是有sqlfiddle.com。

+1

哈哈,你错了。 MySQL有时是愚蠢的:) –

+1

@ypercube:恩,是的。和MS Access用于让你乘以日历日期。 (我不知道它是否仍然有效。)您可以将2013年1月12日的日期乘以2014年2月17日的日期,并获得一些数字。我想,在方形日期中有一些数字。 –

+0

谢谢Mike Sherrill的回答,尤其是谢谢。对于在本地SQL服务器中测试这一点的提示(我已安装了一个,但我在蓝月亮中使用它一次,因为SQL不是我常规工作任务的一部分)。 2月31日的日期是我的一个愚蠢的错字(这就是我得到的冲动)。 – user100487

0

这可以在SQL Server Management Studio(SSMS)中轻松测试。我会回答第一个,你可以自己测试下两个。

问:

A.该DATEADD(1号线)将在2014年3月1日创建日期时间2014年2月31日23:59:59

答:没有,因为二月不可能有31天,所以不能返回“2014-02-31`

证明:

select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0)) 

Results 

(No column name) 
2014-02-28 23:59:59.000 
+0

感谢肯怀特的答案,也为本地测试的提示。 – user100487

0

对于(B)和(C),如果您提出了您的问题,请改为“我的财务年度从2月1日至30日(原文如此)1月份 - 我如何获取当前财政年度的开始日期和结束日期,我会提出:

SET @fysdate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19000201') 

和:

SET @fyedate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19010131') 

(请注意,本次发现的1月31日,而不是30日。我认为你原来的问题是粗心)。 (A),正如我所指出的那样,我认为你的问题再次表达不了 - 如果你试图找到一个时期的终点,那个时期是在日期时间上定义的(而不是仅仅日期),所以可以非常容易构建一个独家上限:

SET @ldpmth = DATEADD(month, DATEDIFF(month,0,GETDATE()),0) 

此结合(成与<比较,而不是<=BETWEEN使用)不人为地排除与时间,例如任何值23:59:59.527。还要注意的是,如果财务年度结束日期计算将用于包含时间的日期时间值,我会再次建议计算上限的独占,并用19010201代替19010131

因此,总的来说,我并不认为我已经回答了您提出的问题,但我想我已经提供了您应该寻求的答案。

+0

谢谢达米安。其实你的回答解释了我对这段代码的一些问题,尽管我不能使用它(因为我需要写一些我可以在Crystal Report设计器中使用的东西)。是的,我确实看到我原来的问题至少有两个日期错别字(1月30日和2月31日)。 – user100487