SQLの日付を扱うとき、月の終わりを計算する必要があることがあります。 月というのは厄介なものです。

では、ある日付が与えられたとき、その月の残りの日数をどのように計算するのでしょうか。

  1. 月の最終日を決定します。

日差の計算はDATEDIFF関数でできますが、月の最終日はどのように計算するのですか?

EOMONTHを使って月末を計算する

SQLサーバー2012以降では、EOMONTH関数を使って月の最終日を返せます。

例えば

SELECT EOMONTH('02/04/2016')

02/29/2016を返す

このようにEOMONTH関数はうるう年を考慮します。

ですから、ある日付から月末までの日数を計算するには

SELECT DATEDIFF(d,'02/04/2016', EOMONTH('02/04/2016'))

この場合は25を返しますと書くことができます。

LoanDate の現在の月の残り日数を計算する、より包括的な例を見てみましょう。

BEGIN TRANSACTION-- Sample DataCREATE TABLE LoanDate (LoanID INT, LoanDate DATE);INSERT INTO LoanDate Values (1, '1/1/2016');INSERT INTO LoanDate Values (1, '1/15/2016');INSERT INTO LoanDate Values (1, '1/31/2016');INSERT INTO LoanDate Values (1, '2/15/2016');INSERT INTO LoanDate Values (1, '3/15/2016');INSERT INTO LoanDate Values (1, '4/15/2016');INSERT INTO LoanDate Values (1, '5/15/2016');INSERT INTO LoanDate Values (1, '6/15/2016');INSERT INTO LoanDate Values (1, '7/15/2016');INSERT INTO LoanDate Values (1, '8/15/2016');INSERT INTO LoanDate Values (1, '9/15/2016');INSERT INTO LoanDate Values (1, '10/15/2016');INSERT INTO LoanDate Values (1, '11/15/2016');INSERT INTO LoanDate Values (1, '12/15/2016');-- Select LoanDate, Days in Month, and Days Remaining in MonthSELECT LoanID, LoanDate, EOMONTH(LoanDate) LoanDateEndOfMonth, DATEDIFF(d, LoanDate, EOMONTH(LoanDate)) as DaysRemainingFROM LoanDateROLLBACK

以下はその結果です:

このように、月によって DaysRemaining が変化します。 また、3行目のように月末と同じ日付の場合は、残り日数が0日であることに注目してください。

では、SQL 2008 R2以前を使用している場合、どのように計算するのかを見てみましょう。

Old School Method to Calculate Last Day of Month

計算方法は、

  1. Determine the last date of the month
  2. Calculate the difference in days, between the date in question and the step 1.

しかし、違いは月の最終日をどう決めるか、という点です。 EOMONTHは利用できないので、「昔ながらの」方法で計算する必要があります。 これにはいくつかの方法があります。 以下はその1つです。

2つの関数を使用して月の最終日を計算します。 DATEADDとDAY.

私たちはDATEADDを使って日付に月を追加します。 次にDAY関数で月の初めから何日目かを求めます。 これを先ほど計算した日付(1ヶ月先の日付)から引くことで、その月の最終日を求めることができます。

さて、わかりにくいと思いますので、この図を使って分解してみましょう:

EOMONTHで行ったのと同じ例を使って、テストに使用できる次のステートメントがあります:

BEGIN TRANSACTION-- Sample DataCREATE TABLE LoanDate (LoanID INT, LoanDate DATE);INSERT INTO LoanDate Values (1, '1/1/2016');INSERT INTO LoanDate Values (1, '1/15/2016');INSERT INTO LoanDate Values (1, '1/31/2016');INSERT INTO LoanDate Values (1, '2/15/2016');INSERT INTO LoanDate Values (1, '3/15/2016');INSERT INTO LoanDate Values (1, '4/15/2016');INSERT INTO LoanDate Values (1, '5/15/2016');INSERT INTO LoanDate Values (1, '6/15/2016');INSERT INTO LoanDate Values (1, '7/15/2016');INSERT INTO LoanDate Values (1, '8/15/2016');INSERT INTO LoanDate Values (1, '9/15/2016');INSERT INTO LoanDate Values (1, '10/15/2016');INSERT INTO LoanDate Values (1, '11/15/2016');INSERT INTO LoanDate Values (1, '12/15/2016');-- Select LoanDate, Days in Month, and Days Remaining in MonthSELECT LoanID, LoanDate, DATEADD(dd,-(DAY(DATEADD(mm,1,LoanDate))), DATEADD(mm,1,LoanDate)) LoanDateEndOfMonth, DATEDIFF(d,LoanDate, DATEADD(dd,-(DAY(DATEADD(mm,1,LoanDate))), DATEADD(mm,1,LoanDate))) as DaysRemainingFROM LoanDateROLLBACK

以下は結果です:

では、どの方法を使用すればいいのでしょうか?

もし私がコードを書いていて、SQLServer 2012以降で動作することがわかっている場合は、EOMONTHメソッドを使用する方が読みやすいと思います。

コメントを残す

メールアドレスが公開されることはありません。