• I had to change EoMonth('1/1/2016',(N-1)) to EoMonth('1/1/2016',(1-n)) for it to work with dates in the past.

    An alternative is to just back up the starting date to cover your date range. If your data starts back in the year 1995, use EoMonth('1/1/1995',N-1). It might be a nice wrinkle to use min(check_date) for the starting date of EOMONTH() and set the TOP() value to be the number of months between the min/max dates in the table.

    declare @MinDate date

    ,@MaxDate date

    ,@Months int

    select @MinDate = min(check_date),@MaxDate = max(check_date) from x_dates

    set @months = datediff(month, @MinDate, @MaxDate) + 1

    select top(@months) EoMONTH(@MinDate, N-1) as EoM from tally

    Fun stuff 😀

    P.S. After all this discussion, we just saved maybe a second from the runtime on this particular query. How many seconds have we all spent thinking about how to do it best? How many times will it have to run to make up for the time we spent? The OP was the wise man: He took the first answer, ran his query and moved on. Philosophically, sometimes good enough is good enough. But then again, twice as fast is twice as fast. If we could make everything run twice as fast, why shouldn't we?

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills