SQLの日付を扱うとき、月の終わりを計算する必要があることがあります。 月というのは厄介なものです。
では、ある日付が与えられたとき、その月の残りの日数をどのように計算するのでしょうか。
- 月の最終日を決定します。
日差の計算は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
計算方法は、
- Determine the last date of the month
- 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メソッドを使用する方が読みやすいと思います。