循环创建新列

时间:2021-04-13 18:58:46

标签: sql sql-server tsql

假设我有一个 SQL Server 表,它有 4 列 MonthEndGenderWeightAge

现在,MonthEnd 从 201901 年到 201912 年。

我有一个运行查询的过程,该查询生成各种指标,例如每个月的 sum(Weight) 和 average(Age)。

现在,我在创建该月的指标时设置了 where MonthEnd = 201901

输出是一个有 2 列和 2 行的表格。 Column1 标题是 Metric,Column2 标题是 201901,然后 row1 column1 表示 Total_Weight,row1 column2 是 sum(weight) 函数生成的值。

同样,row2 column1 表示Average_Age,而row2 column2 是Average(Age) 函数的结果。

以上我都做了。

然后,我必须在将 where 子句更改为 where MonthEnd = 201902 后重新运行代码,然后相同的结构应用于结果。

我希望能够一步运行 201901 到 201912 并让输出反映 13 列,即 column1 仍然是带有标题“Metric”的度量,但接下来的 12 列将有标题 201901 到 201912每个月的相应结果包含在标题下方。

T-SQL 能做到这一点吗?我觉得我可以使用 Pivot 用 1 个聚合函数来完成,但我还没有弄清楚如何同时执行多个聚合函数。

-- THIS SECTION SETS UP THE DATA SET STARTING POINT ---------

IF OBJECT_ID('[dbo].[example]') IS NOT NULL DROP TABLE [dbo].[example]
GO

CREATE TABLE [dbo].[example]
(
MonthEnd INT NOT NULL,
Grade VARCHAR(50) NOT NULL,
Name VARCHAR(50) NOT NULL,
Amount INT NULL
)
GO

INSERT INTO [dbo].[example]
VALUES 
(201901, 'A', 'Josh', 100),
(201901, 'A', 'Joe', 50),
(201901, 'A', 'Jill', 150),
(201901, 'B', 'Julie', 150),
(201901, 'B', 'Jim', 350),
(201901, 'C', 'Jeff', 100),
(201901, 'C', 'Jack', 125),
(201901, 'C', 'Jillian', 150),
(201901, 'C', 'Jess', 175),
(201901, 'C', 'James', 450),
(201902, 'A', 'Josh', 95),
(201902, 'A', 'Jill', 105),
(201902, 'B', 'Julie', 125),
(201902, 'B', 'Jim', 325),
(201902, 'C', 'Jeff', 75),
(201902, 'C', 'Jack', 100),
(201902, 'C', 'Jillian', 125),
(201903, 'A', 'Josh', 50),
(201903, 'B', 'Julie', 75),
(201903, 'B', 'Jim', 300),
(201903, 'C', 'Jeff', 50),
(201903, 'C', 'Jack', 50);

select * from [dbo].[example]

-- THE BELOW SECTION GENERATES THE DESIRED RESULTS WHICH I'D LIKE TO ACHIEVE THROUGH A PIVOT OR LOOP ---
-- I HAVE MONTHS FROM 201801 through 202103, SO I'D LIKE TO ITERATE THROUGH THEM AND PRODUCE THE DESIRED RESULT SET PROGRAMMATICALLY ---

IF OBJECT_ID('tempdb..#temp1') IS NOT NULL drop table #temp1
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL drop table #temp2
IF OBJECT_ID('tempdb..#temp3') IS NOT NULL drop table #temp3

select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'SUM' as Metric
    ,cast(sum(Amount) as varchar(max)) as '201901'
into #temp1
from [dbo].[example] 
where MonthEnd = '201901'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))

    union all

select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'AVG' as Metric
    ,cast(avg(Amount) as varchar(max)) as '201901'
from [dbo].[example] 
where MonthEnd = '201901'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))


select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'SUM' as Metric
    ,cast(sum(Amount) as varchar(max)) as '201902'
into #temp2
from [dbo].[example] 
where MonthEnd = '201902'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))

    union all

select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'AVG' as Metric
    ,cast(avg(Amount) as varchar(max)) as '201902'
from [dbo].[example] 
where MonthEnd = '201902'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))


select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'SUM' as Metric
    ,cast(sum(Amount) as varchar(max)) as '201903'
into #temp3
from [dbo].[example] 
where MonthEnd = '201903'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))

    union all

select 
    cast(Grade as varchar(max)) as Grade
    ,cast(Name as varchar(max)) as Name
    ,'AVG' as Metric
    ,cast(avg(Amount) as varchar(max)) as '201903'
from [dbo].[example] 
where MonthEnd = '201903'
group by 
    cast(Grade as varchar(max))
    ,cast(Name as varchar(max))

select 
    a.Grade
    ,a.Name
    ,a.Metric
    ,a.[201901]
    ,b.[201902]
    ,c.[201903]
from #temp1 a
left join #temp2 b
on  a.Grade = b.Grade and a.Name = b.Name and a.Metric = b.Metric
left join #temp3 c
on  a.Grade = c.Grade and a.Name = c.Name and a.Metric = c.Metric

2 个答案:

答案 0 :(得分:0)

<块引用>

输出是一个有 2 列和 2 行的表格。 Column1 标题是 Metric,Column2 标题是 201901,然后 row1 column1 表示 Total_Weight,row1 column2 是 sum(weight) 函数生成的值。

你已经倒退了。将每个指标设为单独的列,并为每个月和性别设置单独的行。

(月、性别、平均年龄、总体重……)

如果您需要以不同的方式显示数据,请在前端担心,或者在构建结果集后使用 TSQL PIVOT。

答案 1 :(得分:0)

我能够使用枢轴方法来生成所需的结果