Hi Peter,
I really can't thank you enough for taking the time to amend your script. You had no obligation to do so but you did it anyway, I'm very grateful.
In case anyone is bothered I have adapted Peter's script so that it works for multiple years and joins it back to a list of dates to produce 4-4-5 information for all of those dates - in effect a date dimension table with 4-4-5 data. Here it is, although
note that it only works on SQL Server 2012 or SQL Azure (because it uses the DATEFROMPARTS function) (the last three columns pertain to 4-4-5):
--SELECT * FROM ent.Dates
DECLARE @StartYear SMALLINT = 2000,
@EndYear SMALLINT = 2050;
WITH [ctedates]([Cal_Dte]) AS (
SELECT DATEFROMPARTS(@StartYear,1,1)
UNION ALL
SELECT DATEADD(dd,1,d.[Cal_Dte])
FROM [ctedates]d
WHERE d.[Cal_Dte] < DATEFROMPARTS(@EndYear,12,31)
)
,[cteYears]([Yr]) AS (
SELECT [Yr] = @StartYear
UNION ALL
SELECT y.[Yr] + CONVERT(SMALLINT,1)
FROM [cteYears] y
WHERE y.[Yr] < @EndYear
)
,[cteLimits]([Yr],[theFirst], [theLast])
AS (
SELECT y.[Yr]
, [theFirst] = DATEADD(YEAR, y.[Yr] - 1900, '19000101')
, [theLast] = DATEADD(YEAR, y.[Yr] - 1899, '18991231')
FROM [cteYears] y
)
,[cteSource]([Yr],[theDate], [theFirst], [theLast], [ID])
AS (
SELECT l.Yr
, [theDate] = DATEADD(DAY, 7 * sv.[Number], l.[theFirst])
, [theFirst] = l.[theFirst]
, [theLast] = l.[theLast]
, [ID] = sv.[number]
FROM [master]..[spt_values] sv
CROSS JOIN cteLimits l
WHERE sv.[type] = 'P'
AND sv.[number] BETWEEN 0 AND 53
)
, [cteCalendar]([Yr],[theStart], [theEnd], [the13], [the445], [theFirst], [theLast])
AS (
SELECT [Yr]
, [theStart] = DATEADD(DAY, DATEDIFF(DAY, '18991231', theDate) / 7 * 7, '18991231')
, [theEnd] = DATEADD(DAY, DATEDIFF(DAY, '18991231', theDate) / 7 * 7, '19000106')
, [the13] = CASE [ID] / 13 WHEN 4 THEN 3
ELSE [ID] / 13
END
, [the445] = CASE WHEN [ID] = 52 THEN 2
WHEN ([ID] % 13) / 4 = 3 THEN 2
ELSE ([ID] % 13) / 4
END
, [theFirst]
, [theLast]
FROM [cteSource]
)
, [cteWeeks]([Yr],[WeekNumber],[WeekStart], [WeekEnd], [the13], [the445])
AS (
SELECT [Yr]
, [WeekNumber] = ROW_NUMBER() OVER (PARTITION BY [Yr] ORDER BY [theStart])
, [WeekStart] = CASE WHEN [theStart] < [theFirst] THEN [theFirst]
ELSE [theStart]
END
, [WeekEnd] = CASE WHEN [theEnd] > [theLast] THEN [theLast]
ELSE [theEnd]
END
, [the13]
, [the445]
FROM [cteCalendar]
)
SELECT [Dte_EK] = (YEAR(d.[Cal_Dte]) * 10000) + (MONTH(d.[Cal_Dte]) * 100) + (DAY(d.[Cal_Dte]))
, d.[Cal_Dte]
, [CalYr_Nmbr] = YEAR(d.[Cal_Dte])
, [CalMon_Nmbr] = MONTH(d.[Cal_Dte])
, [CalDayOfYr_Nmbr] = DATEPART(dy,d.[Cal_Dte])
, [CalDayOfMon_Nmbr] = DATEPART(dd,d.[Cal_Dte])
, [CalDayOfWk_Nmbr] = DATEPART(dw,d.[Cal_Dte])
, [CalYrMon_Dte_Nmbr] = (YEAR(d.[Cal_Dte]) * 100) + (MONTH(d.[Cal_Dte]))
, [CalMon_Name] = DATENAME(mm,d.[Cal_Dte])
, [CalDayOfWk_Name] = DATENAME(dw,d.[Cal_Dte])
, [CallsMon_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Monday' THEN 1 ELSE 0 END
, [CallsTue_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Tuesday' THEN 1 ELSE 0 END
, [CallsWed_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Wednesday' THEN 1 ELSE 0 END
, [CallsThrs_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Thursday' THEN 1 ELSE 0 END
, [CallsFri_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Friday' THEN 1 ELSE 0 END
, [CallsSat_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Saturday' THEN 1 ELSE 0 END
, [CallsSun_Ind] = CASE DATENAME(dw,d.[Cal_Dte]) WHEN 'Sunday' THEN 1 ELSE 0 END
, [CallsWkDay_Ind] = CASE WHEN DATENAME(dw,d.[Cal_Dte]) NOT IN ('Saturday','Sunday') THEN 1 ELSE 0 END
, [CallsWkend_Ind] = CASE WHEN DATENAME(dw,d.[Cal_Dte]) IN ('Saturday','Sunday') THEN 1 ELSE 0 END
, [CalQtr_Nmbr] = DATEPART(q,d.[Cal_Dte])
, [CalQtr_Name] = CONVERT(CHAR(4),YEAR(d.[Cal_Dte])) + 'CALQ0' + CONVERT(CHAR(1),DATEPART(q,d.[Cal_Dte]))
, [CalWk_Nmbr] = DATEPART(WEEK,d.[Cal_Dte])
, [CalWk_Name] = CONVERT(CHAR(4),YEAR(d.[Cal_Dte])) + 'CALW' + RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(WEEK,d.[Cal_Dte])),2)
, [CalQtr445_Nmbr] = w.[the13] + 1
, [CalMon445_Nmbr] = w.the445 + 1 + (w.[the13] * 3)
, [CalWk445_Nmbr] = w.WeekNumber
FROM [ctedates] d
INNER JOIN [cteWeeks] w ON d.[Cal_Dte] BETWEEN w.[WeekStart] AND w.[WeekEnd]
OPTION (MAXRECURSION 0)
Thanks again Peter.
JT