2

我有这个查询,它选择跨越 iMAXYears 直到 2012 年 11 月 30 日的所有记录:

 SELECT sum([AllocatedAmount]) as total, 
 datediff(day,transactiondate,'30 Nov 2012') / DaysInyear AS YearDiff 
 FROM tblGroups 
 AND datediff(day,transactiondate, '30 Nov 2012') / DaysInyear < iMaxYears
 AND not transactiondate > '30 Nov 2012'  
 GROUP BY g.groupdescription, nominal, 
 datediff(day,transactiondate, '30 Nov 2012') / DaysInyear

就这个问题而言,2012 年 11 月 30 日是硬编码的(变量名 = lMaxDate),iMaxYears 是 3

我的问题是 DaysInYear 通常具有 365 的值,但在闰年将具有 366 的值。

在像 2012 年这样的闰年,由于 2012 年 2 月 29 日,上述语句不会出现在 2011 年 12 月 1 日。

我知道

DaysInYear=(CASE WHEN (year % 4 = 0 AND year % 100 <> 0) 
OR year % 400 = 0 then 366 else 365)

Currently DaysInYear = 365.

我应该创建一个函数

DaysInYear(lYear) where you pass in a year (lYear) 
and it returns 365 or 366?

问题是我不能通过 Year(transactiondate),因为这一年总是跨越 2 年的一部分,而 iMaxYears 意味着我们可以在结果集中有 4 个年度期间。

有任何想法吗?谢谢

4

2 回答 2

0

如果您从 transactionDate 中删除 29 天和 10 个月,您可以将截止点移至 1 月 1 日。这样,DATEADD 会为您计算要减去的正确天数。

CREATE FUNCTION yearDiff(@maxDate DATE, @transactionDate DATE)
RETURNS INT AS
BEGIN
  DECLARE @dayDiff INT
  DECLARE @monthDiff INT

  -- Determine how many months and days @maxDate is from the first of january
  SET @monthDiff = 1 - DATEPART(MONTH, @maxDate)
  SET @dayDiff = 1 - DATEPART(DAY, @maxDate)

  -- Determine how many years away from @maxDate the transaction is
  RETURN DATEDIFF(YEAR,
                  DATEADD(MONTH,
                          @monthDiff,
                          DATEADD(DAY,
                                  @dayDiff,
                                  @transactionDate)
                          ),
                  @maxDate
                  )
END

我认为您的选择将如下所示:

SELECT
  sum(amount) [total],
  dbo.yearDiff(@maxDate, transactionDate) [yearDiff]
FROM tblGroups
WHERE  transactionDate <= @maxDate
AND dbo.yearDiff(@maxDate, transactionDate) <= @iMaxYears
GROUP BY dbo.yearDiff(@maxDate, transactionDate)

http://sqlfiddle.com/#!6/54c2d/2

优点是它很好读,而且你没有神奇的数字。它不是特别有效,如果确实有很多事务,您将需要内联函数调用或者可能为 yearDiff 添加一个计算列。

于 2013-01-23T14:38:51.113 回答
0

如果您只是使用该 case 语句代替 DaysInYear 变量会怎样?

    SELECT sum([AllocatedAmount]) as total, 
 datediff(day,transactiondate,'30 Nov 2012') / CASE WHEN (year % 4 = 0 AND year % 100 <> 0) 
OR year % 400 = 0 then 366 else 365 end AS YearDiff 
 FROM tblGroups 
 AND datediff(day,transactiondate, '30 Nov 2012') / CASE WHEN (year % 4 = 0 AND year % 100 <> 0) 
OR year % 400 = 0 then 366 else 365 end < iMaxYears
 AND not transactiondate > '30 Nov 2012'  
 GROUP BY g.groupdescription, nominal, 
 datediff(day,transactiondate, '30 Nov 2012') / CASE WHEN (year % 4 = 0 AND year % 100 <> 0) 
OR year % 400 = 0 then 366 else 365 end

只要 Year 中的天数基于相关交易日期,您就应该清楚。

于 2013-01-23T14:01:22.060 回答