2

2012 年 11 月 30 日までの iMAXYears にまたがるすべてのレコードを選択する次のクエリがあります。

 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?

問題は、年が常に 2 年の一部にまたがるため、Year(transactiondate) を渡すことができないことです。iMaxYears は、結果セットに 4 つの年間期間を含めることができることを意味します。

何か案は?ありがとう

4

2 に答える 2

0

DaysInYear 変数の代わりにその case ステートメントを使用するとどうなるでしょうか?

    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 に答える
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 に答える