Điều này hoạt động ngay cả khi @StartDate không phải là ngày đầu tiên của tháng. Tôi giả định rằng nếu không phải là đầu tháng, bạn muốn bắt đầu với ngày đầu tiên của tháng tiếp theo. Nếu không, hãy xóa +1.:
;WITH cte AS (
SELECT CASE WHEN DATEPART(Day,@StartDate) = 1 THEN @StartDate
ELSE DATEADD(Month,DATEDIFF(Month,0,@StartDate)+1,0) END AS myDate
UNION ALL
SELECT DATEADD(Month,1,myDate)
FROM cte
WHERE DATEADD(Month,1,myDate) <= @EndDate
)
SELECT myDate
FROM cte
OPTION (MAXRECURSION 0)