-4

我想问 3 个关于以下代码的问题(请原谅冗长的代码清单,我将这些行包括在内是希望它提供足够的上下文)。

请注意,此处的代码取决于执行日期。出于这个原因,我的问题是指具有两个不同执行日期的假设情况:

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

我的问题是我对其中某些部分的理解是否正确,即:

一个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(@yr+@mth+@dy AS NVARCHAR(50)) AS DATETIME))
8. ELSE DATEADD(MM, 1, CAST(CAST((@yr-1)+@mth+@dy AS NVARCHAR(50))
9. AS DATETIME)) END ) 
10. 
11. SET @fyedate = (SELECT CASE WHEN MONTH(@ldpmth) >= 2 THEN
12. DATEADD(YY, 1, CAST(CAST(@yr+@mth+@dy AS NVARCHAR(50)) AS DATETIME)) + 30
13. ELSE  DATEADD(YY, 1, CAST(CAST((@yr-1)+@mth+@dy AS NVARCHAR(50))
14. AS DATETIME)) + 30 END )

(感谢到目前为止所有回答的人。这实际上是几年前在我的工作地点开发(但未记录)的代码,我的任务是将其转换为与 Crystal Reports 一起在客户端工作的表单。 )

4

3 回答 3

2

在 2014 年 3 月 1 日创建日期时间 2014-02-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。

于 2013-06-27T21:37:51.223 回答
0

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

问题:

A. DATEADD(第 1 行)将在 2014 年 3 月 1 日创建日期时间 2014-02-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
于 2013-06-27T21:38:49.217 回答
0

对于(B)和(C),如果您将问题陈述为“我的财政年度从 2 月 1 日到 1 月 30 日(原文如此)-我如何获得当前财政年度的开始和结束日期,我会提供:

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)

这个界限(用于<比较而不是<=or BETWEEN)不会人为地排除任何带有时间的值,例如23:59:59.527. 另请注意,如果要针对包括时间在内的日期时间值使用财政年度结束日期计算,我会再次建议计算一个专属上限,并替换1901020119010131.

所以,总的来说,我认为我并没有真正回答你提出的问题,但我认为我已经提供了你应该寻求的答案。

于 2013-06-28T06:34:12.893 回答