如何根据日期参数创建包含月份列的临时表?

时间:2016-01-06 20:57:57

标签: sql sql-server stored-procedures

我有一个接受两个日期的存储过程。在我的存储过程中,我需要创建一个临时表,其中两个日期之间的月份为列。

例如,

如果用户传入

1/1/2016 , 8/1/2016

我需要一个带有列的临时表:

January February March April May June July August

如何使用以这种方式创建的列创建此类临时表?列是基于传入的两个日期?

2 个答案:

答案 0 :(得分:0)

以下脚本应该让你开始(几乎就在那里):

declare @start_date DATE = '20160101' 
declare @end_date DATE = '20160801'

;WITH CTE AS
(
    SELECT @start_date AS cte_start_date, DATENAME(month, @start_date) AS Name,
        CAST(' ALTER TABLE #myTemp ADD ' + DATENAME(month, @start_date) + ' INT ' + CHAR(13) + CHAR(10) AS VARCHAR(8000)) AS SqlStr
    UNION ALL
    SELECT DATEADD(MONTH, 1, cte_start_date), DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) AS Name, 
        CAST(SqlStr + ' ALTER TABLE #myTemp ADD ' + DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) + ' INT ' + CHAR(13) + CHAR(10) AS VARCHAR(8000))
    FROM CTE
    WHERE DATEADD(MONTH, 1, cte_start_date) <= @end_date   
)
SELECT cte_start_date, Name, SqlStr 
FROM CTE

使用递归CTE,它会在开始日期和结束日期之间生成一个循环,并且每个月都会计算其字符串表示形式,还会创建一个alter script来将列添加到临时表中。

CTE逐步计算SQL脚本,以便最终的脚本位于最后一行。

答案 1 :(得分:0)

试试这个......

declare @start_date DATE = '20160101' 
declare @end_date DATE = '20160801'

;WITH CTE AS
(
    SELECT @start_date AS cte_start_date, DATENAME(month, @start_date) AS NAME , 0 AS Coun
    UNION ALL
    SELECT DATEADD(MONTH, 1, cte_start_date), DATENAME(month, DATEADD(MONTH, 1, cte_start_date)) AS NAME , 0 AS Coun
    FROM CTE
    WHERE DATEADD(MONTH, 1, cte_start_date) <= @end_date   
)

SELECT  Coun,Name
INTO #tmp1
FROM CTE

DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + Name 
                 from #tmp1

        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

set @query = 'SELECT ' + @cols + ' from 
         (
            select Coun,Name
            from #tmp1
        ) x
        pivot 
        (
            MAX(Coun)
            for Name in (' + @cols + ')
        ) p '

execute(@query);
DROP TABLE #tmp1

它将返回OutPut,就像您预期的输出.......