【发布时间】:2021-04-13 18:58:46
【问题描述】:
假设我有一个 SQL Server 表,它有 4 列 MonthEnd、Gender、Weight 和 Age。
现在,MonthEnd 从 201901 到 201912。
我有一个运行查询的过程,该查询会生成各种指标,例如每个月的总和(体重)和平均值(年龄)。
现在,我在创建该月的指标时设置了 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
【问题讨论】:
-
请展示一些示例数据和预期结果以澄清您的问题。
-
添加数据集以反映起点和预期结果
-
所以 - 我最终找到了一种方法来达到预期的结果,但我仍然无法确定我是否可以用循环来做到这一点.....然后再一次,循环可能效率非常低,因为它必须计算每个循环中的所有内容(对吗?)。相反,我使用 UNPIVOT 创建一个“长”数据集而不是“宽”数据集,然后我使用 PIVOT 转换为具有所需结构的“宽”数据集(以月为标题,将指标作为行。 ...)如果人们想看代码,我可以分享。
标签: sql sql-server tsql