Click here to Skip to main content
15,895,011 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
SQL
DECLARE @StartDate DATETIME
       ,@EndDate DATETIME;

SELECT 
    @StartDate ='20100101',
    @EndDate = GETDATE()
      --convert(varchar(8), GETDATE(),112); 

;With DT_TempTbl as
(
   SELECT 
       @StartDate AS YearMonth

   UNION ALL

   SELECT 
       DATEADD(MONTH, 1, YearMonth) 
   FROM 
       DT_TempTbl
   WHERE 
       YearMonth <= @EndDate
)
SELECT
    CONVERT(VARCHAR(6), YearMonth, 112) AS YearMonth1 
FROM 
    DT_TempTbl 
ORDER BY
    YearMonth1
Posted

Here is the reference material for CREATE FUNCTION[^]

The first thing you need to do is move your variables @StartDate and @EndDate out of this SQL to become parameters to the function ... e.g.
SQL
CREATE FUNCTION [dbo].[fnYourFunction] 
( 
    @StartDate DATETIME, 
    @EndDate DATETIME
)
Then you need to define the values you want to return ... in this case you're trying to return the results from
SELECT
    CONVERT(VARCHAR(6), YearMonth, 112) AS YearMonth1
so your output from the function can be defined by
RETURNS @output TABLE(yearmonth VARCHAR(6)

Next include your SQL into the body of the function by surrounding it by BEGIN ... END and including an RETURN statement.

Finally, because you have defined the output table, you just need to add the results from the query into the table e.g.
SQL
INSERT INTO @output

So the whole thing becomes
SQL
CREATE FUNCTION [dbo].[fnYourFunction] 
( 
    @StartDate DATETIME, 
    @EndDate DATETIME
) 
RETURNS @output TABLE(yearmonth VARCHAR(6) 
) 
BEGIN
	With DT_TempTbl as
	(
	   SELECT @StartDate AS YearMonth
 
	   UNION ALL

 	   SELECT DATEADD(MONTH, 1, YearMonth) 
	   FROM DT_TempTbl
	   WHERE  YearMonth <= @EndDate
	)
	INSERT INTO @output
	SELECT CONVERT(VARCHAR(6), YearMonth, 112) AS YearMonth1 
	FROM DT_TempTbl 
	ORDER BY YearMonth1

	RETURN
END
I called it using your test data as follows
SQL
select * from dbo.fnYourFunction(CAST('2010-01-01' as DATETIME), getdate())
 
Share this answer
 
Comments
Richard Deeming 30-Nov-15 8:06am    
For a simple statement like this, it would be better to use an inline TVF.
CHill60 30-Nov-15 9:03am    
Actually, yeah you're right. I got caught up with the how-do-I-create a function idea.
CHill60 30-Nov-15 9:46am    
So I'm guessing you are getting the error "The statement terminated. The maximum recursion 100 has been exhausted before statement completion."
which can be overcome by putting option (maxrecursion 0) just before the RETURN
As I mentioned in the comments to CHill60's answer, an inline table-valued function would be a better choice for this query. This blog post[^] has a comparison of the performance of inline versus multi-statement TVFs.

Rather than using a recursive common table expression, which will have problems with large date ranges, you can use a tally table:
SQL Wizardry Part Eight - Tally Tables[^]

Since you're using SQL 2012, you can use EOMONTH[^] and DATEFROMPARTS[^] to build the dates, and FORMAT[^] to format the date.

Something like this should do the trick:
SQL
CREATE FUNCTION dbo.fnYourFunction()
RETURNS TABLE
As
Return
(
    WITH E1(N) As
    (
        SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
        SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
        SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
    ),
    E2(N) As (SELECT 1 FROM E1 a, E1 b),
    E4(N) As (SELECT 1 FROM E2 a, E2 b),
    E(N) As (SELECT TOP (3660) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4),

    cteMonths As
    (
        SELECT
            D.YearMonth
        FROM
            E
            -- Find the first day of next month:
            CROSS APPLY (VALUES (DateAdd(day, 1, EOMONTH(GetDate())))) As M (EndDate)
            -- Subtract the specified number of months:
            CROSS APPLY (VALUES (DateAdd(month, 1 - E.N, M.EndDate))) As D (YearMonth)
        WHERE
            D.YearMonth >= DateFromParts(Year(GetDate()) - 10, 1, 1)
    )
    SELECT
        FORMAT(YearMonth, 'yyyyMM') AS YearMonth1
    FROM
        cteMonths 
);

NB: You can't use ORDER BY within a TVF. You need to include it in the calling code:
SQL
SELECT 
    YearMonth1 
FROM 
    dbo.fnYourFunction() 
ORDER BY 
    YearMonth1
;
 
Share this answer
 
from the below code it generating the one month extra but i want to be to current month only can any one help me on this please

SQL
DECLARE @StartDate DATETIME
       ,@EndDate DATETIME;
 
SELECT 
    @StartDate ='20100101',
    @EndDate = GETDATE()
      --convert(varchar(8), GETDATE(),112); 

;With DT_TempTbl as
(
   SELECT 
       @StartDate AS YearMonth
 
   UNION ALL
 
   SELECT 
       DATEADD(MONTH, 1, YearMonth) 
   FROM 
       DT_TempTbl
   WHERE 
       YearMonth <= @EndDate
)
SELECT
    CONVERT(VARCHAR(6), YearMonth, 112) AS YearMonth1 
FROM 
    DT_TempTbl 
ORDER BY
    YearMonth1
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900