Tuesday, August 2, 2016

CTE Date Calendar

Hi, now we will see the date calendar of month using CTE (common table expression) and PIVOT table.
Just follow the code:
USE tempdb
GO
----------- Function to return the First Date for month ---------
IF EXISTS(SELECT * FROM SysObjects WHERE NAME = 'f_FirstDayOfMonth' AND XTYPE = 'FN')
      BEGIN
            DROP FUNCTION [f_FirstDayOfMonth]
      END
GO
CREATE FUNCTION [dbo].[f_FirstDayOfMonth]
(@DATE DATE)
RETURNS DATE
AS
BEGIN
DECLARE @ANSWER DATE, @MONTH VARCHAR(2), @YEAR CHAR(4)
SET @MONTH = CASE WHEN DATEPART(MONTH,@DATE) < 10 THEN '0' ELSE '' END + CONVERT(VARCHAR(2), DATEPART(MONTH,@DATE))
SET @YEAR = CONVERT(CHAR(4),DATEPART(YEAR,@DATE))
SET @ANSWER = CONVERT(DATE,@MONTH + '/01/' + @YEAR)
RETURN @ANSWER
END
GO

----------- Function to return the Last Date for month --------
IF EXISTS(SELECT * FROM SysObjects WHERE NAME = 'f_LastdayOfMonth' AND XTYPE = 'FN')
      BEGIN
            DROP FUNCTION [f_LastdayOfMonth]
      END
GO
CREATE FUNCTION [DBO].[f_LastdayOfMonth]
(@DATE DATE)
RETURNS DATE
AS
BEGIN
DECLARE @ANSWER DATE, @MONTH VARCHAR(2), @YEAR CHAR(4)
SET @MONTH = CASE WHEN DATEPART(MONTH,@DATE)<10 THEN '0' ELSE '' END + CONVERT(VARCHAR(2),DATEPART(MONTH,@DATE))
SET @YEAR = CONVERT(CHAR(4),DATEPART(YEAR,@DATE))
SET @ANSWER = CONVERT(DATE,@MONTH + '/01/' + @YEAR)
SET @ANSWER = DATEADD(MONTH,1,@ANSWER)
SET @ANSWER = DATEADD(DAY,-1,@ANSWER)
RETURN @ANSWER
END
GO

--------------- Week Date Calender --------------------------------
IF EXISTS(SELECT * FROM SysObjects WHERE NAME = 'Calendar' AND XTYPE = 'P')
      BEGIN
            DROP PROCEDURE [Calendar]
      END
GO
CREATE PROCEDURE [dbo].[Calendar]
(@MONTH TINYINT,
 @YEAR INT
 )
AS
BEGIN

DECLARE @DATE1 DATE,
        @ENDDATE DATE,
        @DAY1 VARCHAR(10),
        @WEEKID TINYINT,
        @CURRDATE DATE

SELECT @CURRDATE= CONVERT(DATE,(CAST(@YEAR AS CHAR(4))+'-'+CAST(@MONTH AS VARCHAR(2))+'-15'))
SELECT @DATE1=CONVERT(DATE,[dbo].[f_FirstDayOfMonth](@CURRDATE)),@ENDDATE=CONVERT(DATE,[dbo].[f_LastdayOfMonth](@CURRDATE))
SELECT @DAY1= DATENAME(WEEKDAY, @DATE1)

---------- Recursive CTE to get Days and Dates for the month -----------------
;WITH CTE_CAL ([DATE], [DAY], [WEEKID])
 AS
(
 SELECT @DATE1, @DAY1, CASE WHEN DATEPART(WEEKDAY,@DATE1)=1 THEN CAST(DATEPART(WW,@DATE1) AS TINYINT)-1
                            ELSE DATEPART(WW,@DATE1) END AS WEEKID
 UNION ALL
 SELECT DATEADD(DD,1,[DATE]), CAST(DATENAME(WEEKDAY, DATEADD(DD,1,[DATE])) AS VARCHAR(10)), 
        CASE WHEN DATEPART(WEEKDAY,DATEADD(DD,1,[DATE]))=1 THEN CAST(DATEPART(WW,DATEADD(DD,1,[DATE]))AS TINYINT)-1
        ELSE DATEPART(WW,DATEADD(DD,1,[DATE])) END AS WEEKID
 FROM CTE_CAL
 WHERE [DATE] < @ENDDATE
)

------------- Use Pivot to display the result in calendar format ----------- 
SELECT  [WEEKID],[MONDAY],[TUESDAY],[WEDNESDAY],[THURSDAY],[FRIDAY],[SATURDAY],[SUNDAY]
FROM
      (SELECT [WEEKID], [DATE], [DAY] FROM CTE_CAL)
PVT
PIVOT
      (MAX([DATE]) FOR [DAY] IN ([MONDAY],[TUESDAY],[WEDNESDAY],[THURSDAY],[FRIDAY],[SATURDAY],[SUNDAY]))
PVTTAB

END
GO

-- EXEC Calendar 08,2016









Now I write this code another way, most simple way…

DECLARE @MONTH INT = 08
DECLARE @YEAR INT = 2016

;WITH CTE_CAL ([DATE], [DAY])
AS
(SELECT CONVERT(DATE,CONVERT(VARCHAR,(((@YEAR*100)+@MONTH)*100)+1)),
            DATENAME(WEEKDAY,CONVERT(DATE,CONVERT(VARCHAR,(((@YEAR*100)+@MONTH)*100)+1)))
 UNION ALL
 SELECT DATEADD(DD,1,[DATE]),
            DATENAME(WEEKDAY, DATEADD(DD,1,[DATE]))
 FROM CTE_CAL
 WHERE MONTH(DATEADD(DD,1,[DATE])) = @MONTH
)
SELECT *
FROM (SELECT DATEPART(WEEK,[DATE])'WeekID',* FROM CTE_CAL) V1
PIVOT (MAX([DATE]) FOR [DAY]
IN (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday))AS PVT









If there is any other better option,
Please share it here or mail to me arkaa4@gmail.com

Thank You,
Arka Gupta.

No comments:

Post a Comment