vrijdag 8 mei 2015

Getting all (calendar)days within a period


Getting all (calendar)days within a period


Goal


Sometimes you need a list with all days within a specific period, for example to outer join with other tables to have a complete calendar overview. Here is a simple way to get those days.

Solution


Create the Table-Valued Function:

 

CREATE FUNCTION fnGetCalendarDaysInPeriod

(

       @StartDate DATE,

       @EndDate DATE

)

RETURNS TABLE

AS

RETURN

(

       WITH mycte AS

       (

         SELECT CAST(@StartDate AS DATE) DateValue

         UNION ALL

         SELECT  DATEADD(dd, 1, DateValue)

         FROM    mycte  

         WHERE   DATEADD(dd, 1, DateValue) < @EndDate

       )

 

       SELECT  DateValue

       FROM    mycte

)

 

The Function CALL:


DECLARE @StartDate DATE

DECLARE @EndDate DATE

 

SET @StartDate = DATEADD(yy, -2, GETDATE())

SET @EndDate = GETDATE()

 

 

SELECT *

FROM fnGetCalendarDaysInPeriod (@StartDate,@EndDate)

OPTION (MAXRECURSION 0)


Note

Use the Option “MAXRECURSION 0”, otherwise you will exceed the limit of maximum 100 recursions (Default Value).  The “OPTION” clause can be used only at the statement level, so you can’t put this in a “RETURN”.

 

Workaround MAXRECURSION problem:

Return a Table Variable so you can put the “OPTION(MAXRECURSION)” in the “INSERT INTO” statement

CREATE FUNCTION [dbo].[fnGetCalendarDaysInPeriod]

(    

      @StartDate              DATETIME,

      @EndDate                DATETIME

)

RETURNS 

@SelectedRange    TABLE

(IndividualDate DATETIME)

AS

BEGIN

       WITH mycte AS

       (

         SELECT CAST(@StartDate AS DATE) DateValue

         UNION ALL

         SELECT  DATEADD(dd, 1, DateValue)

         FROM    mycte  

         WHERE   DATEADD(dd, 1, DateValue) < @EndDate

       )

 

       INSERT INTO @SelectedRange

       SELECT  DateValue

       FROM    mycte

       OPTION (MAXRECURSION 0);

 

      RETURN

END

GO

 

This will make life much easier for the Developers; they don’t have to care about the “MAXRECURSION” anymore.

Note 2
Using a table valued function can be bad for performance due to the fact that it's treated like a table except there are no statistics available for SQL Server to base a good execution plan on. SQLServer will estimate the function as returning a very small number of rows. If it returns a larger number of rows, then therefore the plan generated could be a lot less than optimal.

Geen opmerkingen: