Use a function like this one, from my answer to Get a list of dates between two dates using a function:
CREATE FUNCTION dbo.ExplodeDates(@startdate datetime, @enddate datetime)
returns table as
return (
with
N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
SELECT DATEADD(day,num-1,@startdate) as thedate
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
);
...and query it like:
SELECT *
FROM YourTable t
CROSS APPLY dbo.ExplodeDates(
DATEFROMPARTS(t.[Year], t.[Month], 1),
EOMONTH(DATEFROMPARTS(t.[Year], t.[Month], 1))
) AS d;
You can use the rank function to get the last two terminalid's:
select terminalid, date, toolid, toolname, workcenterid
from (
select terminalid, date, toolid, toolname, workcenterid
, dense_rank() over ( order by terminalid desc ) as rnk
from T
where date <= now() -- this will be dependent of your DBMS
) as X
where rnk <= 2;
Note that date is a reserved word so it is wise to name the column otherwise. Beside that it is a date of some kind (hard to tell from the question), say transaction_date in lack of a better understanding of your domain.
Best Answer
Shouldn't really need any hacks to handle leap years, but it depends on what results you expect. Typically you just subtract the larger component first, so subtract a month before you subtract a day, instead of the other way around.
Do any of these produce results you don't expect? If so, which ones are "wrong" to you, and why?
You could also consider using a calendar table if you want to handle leap years, holidays, weekends, etc. differently. What you really need to do is fully understand and explain your requirement. With many months having 31 days, and with leap years especially, each possible combination of "today or yesterday last month or year" can be open to multiple interpretations.