I believe it is important to note that the question specifically asks for "full months between" AND that in the examples given each date is treated as "the START point of that date". This latter item is important because some comments state that year-01-31 to year-02-28 is a result of zero. This is correct. 1 complete day in January, plus 27 complete days in February (02-28 is the start of that day, so incomplete) is zero "full" months.
With that in mind I believe the following would meet the requirements IF StartDate is <= EndDate
(DATEPART(YEAR, EndDate) - DATEPART(YEAR, StartDate)) * 12
+ (DATEPART(MONTH, EndDate) - DATEPART(MONTH, StartDate))
- CASE WHEN DATEPART(DAY,EndDate) < DATEPART(DAY,StartDate) THEN 1 ELSE 0 END
To accommodate the possibility that the dates may be in any order then:
, CASE WHEN StartDate <= EndDate THEN
(DATEPART(YEAR, EndDate) - DATEPART(YEAR, StartDate)) * 12
+ (DATEPART(MONTH, EndDate) - DATEPART(MONTH, StartDate))
- CASE WHEN DATEPART(DAY,EndDate) < DATEPART(DAY,StartDate) THEN 1 ELSE 0 END
ELSE
(DATEPART(YEAR, StartDate) - DATEPART(YEAR, EndDate)) * 12
+ (DATEPART(MONTH, StartDate) - DATEPART(MONTH, EndDate))
- CASE WHEN DATEPART(DAY,StartDate) < DATEPART(DAY,EndDate) THEN 1 ELSE 0 END
END AS FullMnthsBtwn
For this sample:
select
StartDate, EndDate
into mytable
from (
values
(cast(getdate() as date),cast(getdate() as date)) -- both same date
-- original
,('2009-04-16','2009-05-15') -- > 0 full month
,('2009-04-16','2009-05-16') -- > 1 full month
,('2009-04-16','2009-06-16') -- > 2 full months
-- '1/31/2018' and endDate of '3/1/2018', I get a 0 – Eugene
, ('2018-01-31','2018-03-01')
-- some extras mentioned in comments, both of these should return 0 (in my opinion)
,('2009-01-31','2009-02-28')
,('2012-12-31','2013-02-28')
,('2022-05-15','2022-04-16') -- > 0 full month
,('2022-05-16','2022-04-16') -- > 1 full month
,('2021-06-16','2022-04-16') -- > 10 full months
) d (StartDate, EndDate)
query
select
StartDate
, EndDate
, CASE WHEN StartDate <= EndDate THEN
(DATEPART(YEAR, EndDate) - DATEPART(YEAR, StartDate)) * 12
+ (DATEPART(MONTH, EndDate) - DATEPART(MONTH, StartDate))
- CASE WHEN DATEPART(DAY,EndDate) < DATEPART(DAY,StartDate) THEN 1 ELSE 0 END
ELSE
(DATEPART(YEAR, StartDate) - DATEPART(YEAR, EndDate)) * 12
+ (DATEPART(MONTH, StartDate) - DATEPART(MONTH, EndDate))
- CASE WHEN DATEPART(DAY,StartDate) < DATEPART(DAY,EndDate) THEN 1 ELSE 0 END
END AS FullMnthsBtwn
from mytable
order by 1
result
+------------+------------+---------------+
| StartDate | EndDate | FullMnthsBtwn |
+------------+------------+---------------+
| 2009-01-31 | 2009-02-28 | 0 |
| 2009-04-16 | 2009-05-15 | 0 |
| 2009-04-16 | 2009-05-16 | 1 |
| 2009-04-16 | 2009-06-16 | 2 |
| 2012-12-31 | 2013-02-28 | 1 |
| 2018-01-31 | 2018-03-01 | 1 |
| 2021-06-16 | 2022-04-16 | 10 |
| 2022-05-15 | 2022-04-16 | 0 |
| 2022-05-16 | 2022-04-16 | 1 |
| 2022-07-09 | 2022-07-09 | 0 |
+------------+------------+---------------+
See db<>fiddle here (compares some other responses as well)