What would be the SQL to calculate the number of days in each year if I had a start date and the number of days that have lapsed?
For example, the date (ymd) 2013-01-01 and the days lapsed is 1000.
I would like the result to look like this
2013 = 365
2014 = 365
2015 = 270
Can this be written as a function like datediff
?
I have tried using a calendar table, but of course, linking to this just gives me 2013 = 1000
My calendar table looks like this.
DATE_ID | DATE | CALENDAR_YEAR | FINANCIAL_YEAR ----------------------------------------------- 20130101 | 2013-01-01 | 2013 | 2013/14
This is what i have tried.
SELECT
D.FISCAL_YEAR, SUM([DAYS]) AS NUMBER_OF_DAYS
FROM [dbo].[FACT] F
LEFT JOIN [dbo].[DIM_DATE] D ON D.DATE_ID = F.DATE_ID
GROUP BY
D.FISCAL_YEAR
The result for this is.
FISCAL_YEAR | NUMBER_OF_DAYS ---------------------------- 2013/14 |2820 2014/15 |6635 2015/16 |2409
Advertisement
Answer
I would personally build a tally table to do this. Once you build that, you can easly get every date and count the number of days in each year:
DECLARE @YMD date = '20130101', @Lapsed int = 1000; --Build a Tally table WITH N AS( SELECT N FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)), Tally AS( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I FROM N N1, N N2, N N3, N N4), --10,000 should be enough --Build the dates table Dates AS( SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate FROM Tally T WHERE T.I <= @Lapsed - 1) --And count the days SELECT DATEPART(YEAR, CalendarDate) AS Year, COUNT(CalendarDate) AS Days FROM Dates D GROUP BY DATEPART(YEAR, CalendarDate);
As a function:
CREATE FUNCTION CountDays (@YMD date, @Lapsed int) RETURNS table AS RETURN --Build a Tally table WITH N AS( SELECT N FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)), Tally AS( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I FROM N N1, N N2, N N3, N N4), --10,000 should be enough --Build the dates table Dates AS( SELECT DATEADD(DAY, T.I, @YMD) AS CalendarDate FROM Tally T WHERE T.I <= @Lapsed - 1) --And count the days SELECT DATEPART(YEAR, CalendarDate) AS Year, COUNT(CalendarDate) AS Days FROM Dates D GROUP BY DATEPART(YEAR, CalendarDate); GO SELECT * FROM (VALUES('20130101',1000), ('20150501',755))V(YMD, Lapsed) CROSS APPLY dbo.CountDays(V.YMD,V.Lapsed) CD;