'build month Start and End dates intervals SQL
Solution 1:[1]
You can use EOMONTH function and DATEADD function to get the data you want.
But, the best approach would be to use a calendar table and map it against the current date and get the data you want.
DECLARE @DATE DATE = getdate()
SELECT DATEADD(DAY,1,EOMONTH(@DATE,-1)) AS MonthM_Start, EOMONTH(@DATE) AS MonthM_End,
DATEADD(DAY,1,EOMONTH(@DATE,-2)) AS MonthOneBack_Start, EOMONTH(@DATE,-1) AS MonthOneBack_End,
DATEADD(DAY,1,EOMONTH(@DATE,-3)) AS MonthTwoBack_Start, EOMONTH(@DATE,-2) AS MonthTwoBack_End,
DATEADD(DAY,1,EOMONTH(@DATE,-4)) AS MonthThreeBack_Start, EOMONTH(@DATE,-3) AS MonthThreeBack_End
| MonthM_Start | MonthM_End | MonthOneBack_Start | MonthOneBack_End | MonthTwoBack_Start | MonthTwoBack_End | MonthThreeBack_Start | MonthThreeBack_End |
|---|---|---|---|---|---|---|---|
| 2022-03-01 | 2022-03-31 | 2022-02-01 | 2022-02-28 | 2022-01-01 | 2022-01-31 | 2021-12-01 | 2021-12-31 |
Solution 2:[2]
You can use a recursive CTE to avoid having to hard-code an expression for each month boundary you need, making it very easy to handle fewer or more months by just changing a parameter.
Do you really need the end date for processing? Seems more appropriate for a label, since date/time types can vary - meaning the last day of the month at midnight isn't very useful if you're trying to pull any data from after midnight on the last day of the month.
This also shows how to display the data for each month even if there isn't any data in the table for that month.
DECLARE @number_of_months int = 4,
@today date = DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);
;WITH m(s) AS
(
SELECT @today UNION ALL SELECT DATEADD(MONTH, -1, s) FROM m
WHERE s > DATEADD(MONTH, 1-@number_of_months, @today)
)
SELECT MonthStart = m.s, MonthEnd = EOMONTH(m.s)--, other cols/aggs
FROM m
--LEFT OUTER JOIN dbo.SourceTable AS t
--ON t.datetime_column >= m
--AND t.datetime_column < DATEADD(MONTH, 1, m);
Output (without the join):
MonthStart MonthEnd 2022-03-01 2022-03-31 2022-02-01 2022-02-28 2022-01-01 2022-01-31 2021-12-01 2021-12-31
- Example db<>fiddle
But, as mentioned in a comment, you could easily store this information in a calendar table, too, and just outer join to that:
SELECT c.TheFirstOfMonth, c.TheLastOfMonth --, other cols/aggs
FROM dbo.CalendarTable AS c
LEFT OUTER JOIN dbo.SourceTable AS t
ON t.datetime_column >= c.TheFirstOfMonth
AND t.datetime_column < c.TheFirstOfNextMonth
WHERE c.FirstOfMonth >= DATEADD(MONTH, -4, GETDATE())
AND c.FirstOfMonth < GETDATE();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Venkataraman R |
| Solution 2 |

