2017-01-05 18 views
0

日付と年に基づいてSQLで膨大な計算が行われています。月に日付を追加すると、日数に基づいて追加されず、主に3ヶ月追加されます(その機能の機能)。DATEADD関数の問題

例えば、SELECT DATEADD(month, 4, '2016-10-25')。これは私が何を期待しているのかを2017-02-25

と取り上げていますが、これを行うとDATEADD(month, 4, '2016-10-30')となります。その取得2017-02-28。それは私が期待しているものではありません。私はこの機能が月を追加して、その月の最後の日に持っていくことを知っています。

この場合、出力が2016-02-30として表示されるようにするには、日付が存在しないことがわかっているため可能です。 2017-02-28の代わりに2017-03-01を返すようにプログラムすることは可能でしょうか。 (これは2月29日のようにうるう年に大きな問題になります)

本当にありがとうございます。ありがとうございました。

+1

しかし、あなたが実際に望む結果になるためにこれを試してみてください?。あなたは代わりに日を追加したいかもしれませんが、28、他の30,31を持っているいくつかの月に対処しなければならないかもしれません.... – Lamak

+2

なぜ月を追加しているのか、あなたは適切な答えを得ることができます – Tanner

+0

'2016-02-30'は有効な日付ではありません。うるう年には29ユーロに戻りますが、それを試しましたか? 2016年は2017年ではなくうるう年です。私はそれが必要なものであれば、日々のアプローチに同意します。いくつかの月は31日連続している(7月と8月、12月と1月)ので、その機能を期待している場合、月は一貫性のある間隔のようには見えません。 – ps2goat

答えて

0

明らかに、合理的なソフトウェアシステムは2017-02-30を生み出すことはないでしょう。それはあまりにも多くのことを求めています。

あなたの代わりに月の最後の日に行くの翌月に行きたい場合は、あなたが行うことができます:

select (case when day(d) <= 28 or day(d) = day(dateadd(month, 4, d)) 
      then dateadd(month, 4, d) 
      else dateadd(month, 5, dateadd(day, 1 - day(d), day) 
     end) 

これは言う:4ヶ月の追加

  1. はとても細かいです4ヵ月後の日が今月の日と同じである限り長くしてください。
  2. それ以外の場合は、5か月後の月の初めに行ってください。
1

あなたはに追加された月の日数に基づいていくつかの計算を行うと、先の月が何日ということはありません余分な日追加することができます。

CREATE TABLE #dates (val DATE); 

INSERT INTO #dates 
     (val) 
VALUES ('20160131'), 
     ('20160130'), 
     ('20160129'); 

SELECT val , 
     DATEADD(MONTH, 1, val) StandardMonthAdd , 
     CASE WHEN DATEPART(DAY, val) != DATEPART(DAY, DATEADD(MONTH, 1, val)) 
      THEN DATEADD(DAY, 
          DATEPART(DAY, val) - DATEPART(DAY, 
                 DATEADD(MONTH, 1, val)), 
          DATEADD(MONTH, 1, val)) 
      ELSE DATEADD(MONTH, 1, val) 
     END CalculatedMonthAdd 
FROM #dates; 

DROP TABLE #dates; 

を生成します:

val   StandardMonthAdd CalculatedMonthAdd 
2016-01-31 2016-02-29   2016-03-02 
2016-01-30 2016-02-29   2016-03-01 
2016-01-29 2016-02-29   2016-02-29 

これは、2月に31日、2日に2を追加したいので、レコード1に対して1日追加すると仮定します。

+0

解決法を教えていただきありがとうございます。 – Naga

0

は2月31日など

-- ================================================ 
-- Template generated from Template Explorer using: 
-- Create Scalar Function (New Menu).SQL 
-- 
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below. 
-- 
-- This block of comments will not be included in 
-- the definition of the function. 
-- ================================================ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
-- ============================================= 
-- Author:  <Author,,Name> 
-- Create date: <Create Date, ,> 
-- Description: <Description, ,> 
-- ============================================= 
create FUNCTION fn_Add_Full_Months 
(
    -- Add the parameters for the function here 
    @DATE as datetime, 
    @MONTHADD as int 
) 
RETURNS nvarchar(10) 
AS 
BEGIN 
    -- Declare the return variable here 

    DECLARE @DAYS as int = DAY(@DATE); 
    DECLARE @MONTHS as int = MONTH(@DATE); 
    DECLARE @YEARS as int = YEAR(@DATE); 

    DECLARE @TRIAL as int = @YEARS*12 + @MONTHS - 1 + @MONTHADD; 

    RETURN CAST(@TRIAL/12 AS nvarchar(4)) + '-' + 
       RIGHT('0' + CAST(@TRIAL % 12 + 1 AS nvarchar(4)), 2) + '-' + 
       RIGHT('0' + CAST(@DAYS AS nvarchar(4)), 2); 

END 
GO 

その後、

select dbo.fn_Add_Full_Months('19960131', 1); 
+0

Catoさんありがとうございます。しかし、これを日付に変換することはできません。存在しないため、これを文字列として操作する必要がありますか? – Naga

+0

@naga - 正しいと思います。文字列の中に存在しない文字列を1つ変更すると、エラーが発生します。不正な日付をユーザーに表示することは悪い考えかもしれません。他のアイデアの方が良いかもしれません。 – Cato