【问题标题】:Dynamically create table columns with values from Pivot Table使用数据透视表中的值动态创建表列
【发布时间】:2019-11-07 13:53:59
【问题描述】:

我有一个使用数据透视函数的动态查询,以下是我的表中的数据示例。

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。因此,我需要创建表。但是,如果我尝试使用预期的最大列数 (6) 创建表,我将收到无效的列数错误。例如,在我的数据库中我只有两个星期,这就是为什么我只能创建包含 weekA 和 weekB 列的表。我也无法选择进入。

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

感谢您提供的任何帮助。

【问题讨论】:

    标签: sql tsql sql-server-2008-r2


    【解决方案1】:

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

    您可以测试更改 Week_No 值的代码

    对于您的最终查询,只需在删除 CTE 代码后使用 SELECT 部分

    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
    ') 
    

    【讨论】:

    • 对您如何将我复杂的查询变成如此简单的事情印象深刻
    • 很高兴听到它有帮助:)
    • 我们正在传递变量,我们是否有受到注入攻击的危险?
    • 这实际上取决于您如何实施该过程。我在这里也有知识湖,一些谷歌搜索可以帮助我们俩:)这篇文章对我们来说是一个很好的起点-paladion.net/blogs/…
    猜你喜欢
    • 2019-12-22
    • 2014-10-18
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多