/* Test Project table definition and data load./DECLARE @ProjectList table(Proj_ID int,Proj_Name varchar(60),Proj_Start datetime,Proj_End datetime)INSERT INTO @ProjectListSELECT1 AS Proj_ID,'Discuss Building' AS Proj_Name,'1997-01-15' AS Proj_Start,'1997-07-20' AS Proj_EndUNIONSELECT2 AS Proj_ID,'Draw Building Plan' AS Proj_Name,'1997-07-21' AS Proj_Start,'1998-09-15' AS Proj_EndUNIONSELECT3 AS Proj_ID,'Argue About Fees' AS Proj_Name,'1998-03-01' AS Proj_Start,'1999-10-20' AS Proj_EndUNIONSELECT4 AS Proj_ID,'Groundbreaking' AS Proj_Name,'1998-11-01' AS Proj_Start,'1998-11-02' AS Proj_EndUNIONSELECT5 AS Proj_ID,'Construction' AS Proj_Name,'1998-11-01' AS Proj_Start,'2001-05-06' AS Proj_EndUNIONSELECT6 AS Proj_ID,'Stock The Supplies' AS Proj_Name,'2001-01-04' AS Proj_Start,'2001-07-20' AS Proj_EndUNIONSELECT7 AS Proj_ID,'Order The Books' AS Proj_Name,'2001-06-01' AS Proj_Start,'2003-06-30' AS Proj_EndUNIONSELECT8 AS Proj_ID,'Publisher Problems' AS Proj_Name,'2001-07-01' AS Proj_Start,'2004-08-18' AS Proj_EndUNIONSELECT9 AS Proj_ID,'Stock The Shelves' AS Proj_Name,'2002-02-01' AS Proj_Start,'2005-03-27' AS Proj_EndUNIONSELECT10 AS Proj_ID,'Library Is Open' AS Proj_Name,'2004-11-01' AS Proj_Start,'2012-12-11' AS Proj_End/* Test Work table definition and data load./DECLARE @WorkTable table(Work_ID int,Work_Start datetime,Work_End datetime)INSERT INTO @WorkTableSELECT 1, '1997-01-15', '1998-01-14'UNION SELECT 2, '1997-02-01', '1997-03-01'UNION SELECT 3, '1997-03-01', '1997-04-01'UNION SELECT 4, '1997-04-01', '1997-05-01'UNION SELECT 5, '1997-05-01', '1997-06-01'UNION SELECT 6, '1997-06-01', '1997-07-01'UNION SELECT 7, '1997-07-01', '1997-08-01'UNION SELECT 8, '1997-08-01', '1997-09-01'UNION SELECT 9, '1997-09-01', '1997-10-01'UNION SELECT 10, '1997-10-01', '1997-11-01'UNION SELECT 11, '1997-11-01', '1997-12-01'UNION SELECT 12, '1997-12-01', '1998-01-01'UNION SELECT 13, '1998-01-01', '1998-02-01'UNION SELECT 14, '1998-02-01', '1998-03-01'UNION SELECT 15, '1998-03-01', '1998-04-01'UNION SELECT 16, '1998-04-01', '1998-05-01'UNION SELECT 17, '1998-05-01', '1998-06-01'UNION SELECT 18, '1998-06-01', '1998-07-01'UNION SELECT 19, '1998-07-01', '1998-08-01'UNION SELECT 20, '1998-08-01', '1998-09-01'UNION SELECT 21, '1998-09-01', '1998-10-01'UNION SELECT 22, '1998-10-01', '1998-11-01'UNION SELECT 23, '1998-11-01', '1998-12-01'UNION SELECT 24, '1998-12-01', '1999-01-01'UNION SELECT 25, '1999-01-01', '1999-02-01'UNION SELECT 26, '1999-02-01', '1999-03-01'UNION SELECT 27, '1999-03-01', '1999-04-01'UNION SELECT 28, '1999-04-01', '1999-05-01'UNION SELECT 29, '1999-05-01', '1999-06-01'UNION SELECT 30, '1999-06-01', '1999-07-01'UNION SELECT 31, '1999-07-01', '1999-08-01'UNION SELECT 32, '1999-08-01', '1999-09-01'UNION SELECT 33, '1999-09-01', '1999-10-01'UNION SELECT 34, '1999-10-01', '1999-11-01'UNION SELECT 35, '1999-11-01', '1999-12-01'UNION SELECT 36, '1999-12-01', '2000-01-01'UNION SELECT 37, '2000-01-01', '2000-02-01'UNION SELECT 38, '2000-02-01', '2000-03-01'UNION SELECT 39, '2000-03-01', '2000-04-01'UNION SELECT 40, '2000-04-01', '2000-05-01'UNION SELECT 41, '2000-05-01', '2000-06-01'UNION SELECT 42, '2000-06-01', '2000-07-01'UNION SELECT 43, '2000-07-01', '2000-08-01'UNION SELECT 44, '2000-08-01', '2000-09-01'UNION SELECT 45, '2000-09-01', '2000-10-01'UNION SELECT 46, '2000-10-01', '2000-11-01'UNION SELECT 47, '2000-11-01', '2000-12-01'UNION SELECT 48, '2000-12-01', '2001-01-01'UNION SELECT 49, '2001-01-01', '2001-02-01'UNION SELECT 50, '2001-02-01', '2001-03-01'UNION SELECT 51, '2001-03-01', '2001-04-01'UNION SELECT 52, '2001-04-01', '2001-05-01'UNION SELECT 53, '2001-05-01', '2001-06-01'
/* This section creates a table variable to hold the calendar information. This can be used as a speed increase in the other CTE. Defining the table variable (@CalTable) with a primary key and unique index helps to reduce to total time used to find all of the records./DECLARE @CalTable table(CalDate datetime PRIMARY KEY CLUSTERED,CalYear int,CalMonth int,UNIQUE NONCLUSTERED (CalDate));WITHCalBaseList AS Recursive CTE to build the initial calendar table based on the date ranges.(SELECTMIN(pl.Proj_Start) AS CalStart,MAX(pl.Proj_End) AS CalEndFROM @ProjectList AS plWHERE pl.Proj_ID = 7 pl.Proj_ID BETWEEN 2 AND 6UNION ALLSELECTDATEADD(dd, 1, CalStart) AS CalStart,CalEndFROM CalBaseListWHEREDATEADD(dd, 1, CalStart) <= CalEnd),CalList AS Filters out any unwanted dates (Weekends, Holidays).(SELECTs2.CalDate,DATEPART(yy, s2.CalDate) AS CalYear,DATEPART(mm, s2.CalDate) AS CalMonthFROM(SELECTs1.CalDate,DATEPART(dw, s1.CalDate) AS DayFlag,( Uses routines defined in this article: http://www.sqlservercentral.com/articles/SQL/69774/ SELECT COUNT(*) FROM dbo.fn_ActivityForDay(s1.CalDate, 0) WHERE ReportFlag = 1 AND DayOffFlag = 1) AS HolidayFlag0 AS HolidayFlagFROM(SELECTCalStart AS CalDateFROM CalBaseList) AS s1) AS s2WHEREs2.DayFlag <> 1 SundayAND s2.DayFlag <> 7 SaturdayAND s2.HolidayFlag = 0 Holiday Count)INSERT INTO @CalTable Load the Calendar Table.SELECTcl.CalDate,cl.CalYear,cl.CalMonthFROM CalList AS clOPTION (MAXRECURSION 0)
/* Find dates with the BETWEEN method./ 11, 5, 5 seconds.SELECTwt.Work_ID,ct.CalDate,ct.CalYear,ct.CalMonthFROM @WorkTable AS wtLEFT JOIN @CalTable AS ct ONct.CalDate BETWEEN wt.Work_Start AND wt.Work_End
/* Find dates with the individual date range checks./SELECT 5, 3, 3 secondswt.Work_ID,ct.CalDate,ct.CalYear,ct.CalMonthFROM @WorkTable AS wtLEFT JOIN @CalTable AS ct ONwt.Work_Start <= ct.CalDateWHERE(CASEWHEN ct.CalDate <= wt.Work_End THEN 1ELSE 0END) = 1