动态使用列值作为列

Use Column Values as Columns dynamically

我有一个查询,它使用一堆案例语句按部门和员工 ID 汇总销售额,并将月份和年份作为列标题。目前,我正在为每个独特的月份和年份使用 Case 语句。我的目标是尝试找到一种更动态的方法来实现相同的结果,而不必为 Mnth_Yr 列中的每个新值添加额外的 case 语句。

我曾尝试使用 PIVOT,但结果是所有行值都被转换为列,而不仅仅是 Mnth_Yr 列。

这是数据示例。

这是我希望达到的预期结果。

这是我正在使用的代码。

    IF OBJECT_ID('tempdb.dbo.#table_data') IS NOT NULL
    DROP TABLE #table_data
    
    CREATE table #table_data
    ([Division] varchar(15), [Emp_Id] int, [Mnth_Yr] int, [Sales] money)
    
INSERT INTO #table_data
    ([Division], [Emp_Id], [Mnth_Yr], [Sales])
VALUES
    ('Northeast', 625, 202101, 310.58),
    ('Northeast', 627, 202101, 252.83),
    ('Southeast', 158, 202101, 5871.12),
    ('Southeast', 487, 202101, 1587.58),
    ('Northeast', 625, 202102, 521.87),
    ('Northeast', 627, 202102, 870.24),
    ('Southeast', 158, 202102, 7812.17),
    ('Northeast', 625, 202103, 564.57),
    ('Northeast', 627, 202103, 251.61),
    ('Southeast', 158, 202103, 15780.45),
    ('Southeast', 487, 202103, 1770.51)
;
----------------------------------------------------------------------

select Division
, Emp_Id
, SUM(Case When Mnth_Yr = 202101 Then Sales ELSE null END) as "202101"
, SUM(Case When Mnth_Yr = 202102 Then Sales ELSE null END) as "202102"
, SUM(Case When Mnth_Yr = 202103 Then Sales ELSE null END) as "202103"

from #table_data
Group by Division
, Emp_Id

My goal is to try to find a more dynamic method to achieve the same result without having to add additional case statements for every new value that ends up in the Mnth_Yr column.* -

你有点不能,除非你使用动态 SQL..这是有原因的;数据库 table 的列就像事物的 属性 - 它们不是动态的,如果它们是动态的则很难使用。使用您的数据库的其他系统希望您的订单上有总计、姓名、地址等字段 table.. 他们真的不知道如何处理本周没有 NumberofItemsFulfilledInFirstWeekOfJan 和下周的订单一周呢。一直向上编写支持事物动态属性的系统,一直到人类用户,是一项艰巨的工作

我建议您考虑调整数据范围,而不是提供 202101、202102 的列,而是考虑提供每年都有一定意义的固定名称;称他们为一月、二月、三月。使用基于当前年份(通过参数或服务器时钟)选择数据的 where 子句,并给出“一月”含义的上下文

如果您不想这样做,那很好 - 但坚持“查询输出的列数不打算根据今天的日期或最近发生的事情动态变化”的口头禅有帮助开发数据库驱动的软件——应该变化的是 的数量,而不是列的数量。您希望将数据库用作演示工具,而实际上这种旋转操作应该由前端应用程序中的图表软件执行 - 它可以接收可变数量的行和固定数量的列并生成网格

如果您执意要让数据库执行此操作并让您的列无限可变,那么您将需要编写代码来动态生成查询,运行 它,然后使用它- 它可以是数据库中的存储过程之类的东西,或者是查询变体数量的前端语言,并将 SQL 字符串和 运行s 连接在一起,并输出结果..

..但是没有办法对你的数据库说“使用这个固定的 sql 查询来在 x 上旋转这个数据并给我一个今天有 y 列的结果集,但明天 z “

嗯,这与上面提到的方法不完全一样,但它可以满足我使用 XML 的需要。

DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX);
SET @cols = STUFF(
                 (
                     SELECT DISTINCT
                            ','+QUOTENAME(c.Mnth_Yr)
                     FROM #table_data c FOR XML PATH(''), TYPE
                 ).value('.', 'nvarchar(max)'), 1, 1, '');
SET @query = 'SELECT Division, Emp_Id, '+@cols+'from (SELECT Division,
           Emp_Id,
           sum(sales) AS [amount],
           Mnth_Yr AS [category]
    FROM #table_data
    Group by Division,
           Emp_Id,
           Mnth_Yr
    )x pivot (max(amount) for category in ('+@cols+')) p';
EXECUTE (@query);