使用 Pivot Table 中的值动态创建 table 列

Dynamically create table columns with values from Pivot Table

我有一个使用数据透视函数的动态查询,以下是我 table.

中的数据示例
Status 1  | Week 1 |25
Status 1  | Week 1 |25
Status 1  | Week 2 |25
Status 2  | Week 1 | 2
Status 2  | Week 1 | 8
Status 2  | Week 1 | 10
Status 2  | Week 1 | 10 

这是数据返回方式的示例。

            Week 1        Week 2    
Status 1 |    50            25
Status 2      10            20

对于我的查询,我将在一周内传递,我想在接下来的 5 周内进行调整,例如,如果我传递 1 周,我希望有从第 1 周到第 6 周的列。 为了帮助方便,我编写了以下查询。

--EXEC usp_weekReport @weeks=1, @year='2019'
ALTER PROC usp_weekReport
(
@weeks INT,
@year NVARCHAR(4)

)
AS
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @csql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME([week]) 
  FROM (
  SELECT p.[week] 
  FROM [Housing_support_DB].[dbo].[Invoices] P 
  WHERE DATEPART(YEAR,P.date)='2019'--@year
  AND 
  ([week] IN (1)
  OR
  [week] IN (1+1)
    OR
  [week] IN (1+2)
    OR
  [week] IN (1+3)
    OR
  [week] IN (1+4)
    OR
  [week] IN (1+5) 
  )
  GROUP BY P.[week] 

  ) AS x;
SET @sql = N'
SELECT p.[statusName],' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT 
    SUM(CAST(REPLACE(REPLACE(A.amount,'','',''''),''$'','''') AS FLOAT)) as sumInvoice,
  A.invoiceStatusID_FK,
  B.statusName,
--  C.programme,
  [week]
  FROM [dbo].[Invoices] A
  INNER JOIN invoiceStatus B
  ON A.invoiceStatusID_FK=B.invoiceStatusID
--  INNER JOIN CapitalAccountBalances C
 -- ON C.accountBalanceID=A.accountBalanceID_FK 
 -- WHERE A.accountBalanceID_FK=5
 GROUP BY invoiceStatusID_FK,B.statusName,[week]--,C.programme
) AS j
PIVOT
(
  SUM(sumInvoice) FOR [week] IN ('
  + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
  + ')
) AS p;';
--PRINT @sql;
EXEC sp_executesql @sql;
--SET @csql = N'
--CREATE TABLE ##reportResult
--(
--statusName nvarchar(50),'+
CREATE TABLE ##reportResult
(
statusName nvarchar(50),
weekA INT DEFAULT 0,
 weekB int DEFAULT 0--,
--weekC int DEFAULT 0,
--weekD int DEFAULT 0,
--weekE int DEFAULT 0,
--weekF int DEFAULT 0
)
 INSERT  into  ##reportResult Exec(@sql)
--INSERT ##reportResult Exec(@sql)
--SELECT statusName, weekA,weekB,weekC,weekD,weekE,weekF -- here you have "static SELECT with field names"
--FROM ##reportResult 
--DROP TABLE ##reportResult

问题

我在这里遇到的最大问题是,我需要将此查询的结果发送到 tempTable...#reportResult。因此,我需要创建 table。但是,如果我尝试使用预期的最大列数 (6) 创建 table,我将收到无效的列数错误。例如,在我的数据库中我只有两周时间,这就是为什么我只能创建包含列 weekA 和 weekB 的 table 的原因。我也不能做一个 select 进去。

目前,我正在尝试找到一种方法来根据数据透视表 table 的第一部分开始的周数动态创建 table。或者,为了在 运行 时将数据透视表的第一部分操作为 select 周、周+1 等作为列,这样我就可以创建包含所有字段的列。

感谢您提供的任何帮助。

您的情况需要动态 SQL,因为需要根据输入的周数生成列名。下面我为您提供了我使用 CTE 使用您的示例数据创建的脚本。您只需要根据您的 table 和要求更新脚本。

You can test the code changing the value of Week_No

For your final query, just use the SELECT part after removing the CTE code

DECLARE @Week_No INT = 2
DECLARE @Loop_Count INT = 1
DECLARE @Column_List VARCHAR(MAX) = '[Week '+CAST(@Week_No AS VARCHAR) +']'

WHILE @Loop_Count < 5
BEGIN
    SET @Column_List = @Column_List +',[Week '+CAST(@Week_No+@Loop_Count AS VARCHAR) +']'
    SET @Loop_Count = @Loop_Count + 1
END

--SELECT @Column_List
EXEC
('
    WITH your_table(Status,Week_No,Val)
    AS
    (
    SELECT ''Status 1'',''Week 1'',25 UNION ALL
    SELECT ''Status 1'',''Week 1'',25 UNION ALL
    SELECT ''Status 1'',''Week 2'',25 UNION ALL
    SELECT ''Status 2'',''Week 1'',2 UNION ALL
    SELECT ''Status 2'',''Week 1'',8 UNION ALL
    SELECT ''Status 2'',''Week 1'',10 UNION ALL
    SELECT ''Status 2'',''Week 1'',10 
    )


    SELECT * FROM
    (
        SELECT * FROM your_table
    ) AS P
    PIVOT
    (
        SUM(val)
        FOR Week_No IN ('+@Column_List+')
    )PVT
')