反透视具有多列的数据 - 请语法帮助
Posted
技术标签:
【中文标题】反透视具有多列的数据 - 请语法帮助【英文标题】:Unpivot Data with Multiple Columns - Syntax Help Please 【发布时间】:2014-07-18 04:21:40 【问题描述】:我有以下数据要取消透视
我创建了这个查询来取消透视“实际”行,但似乎无法弄清楚取消透视“Plan”和“PriorYear”的语法。
SELECT FiscalYear, Period, MetricName, ActualValue
FROM vw_ExecSummary
UNPIVOT
(ActualValue FOR MetricName IN ( [Net Revenue], [Total C.S. Salaries]
)) AS unpvt
WHERE [Type] = 'Actual'
未透视的数据看起来像这样,但我还想在下方 ActualValue 列的右侧添加 Plan 和 PriorYear 列
任何帮助将不胜感激。谢谢。
【问题讨论】:
【参考方案1】:我目前无法对此进行测试,但我认为它是这样工作的。首先,你需要UNPIVOT
所有数据:
SELECT fiscalYear, period, type, metricName, metricValue
FROM vw_ExecSummary
UNPIVOT (metricValue FOR metricName IN ([Net Revenue], [Total C.S. Salaries])) unpvt
这应该会导致一个看起来像这样的表格:
fiscalYear period type metricName metricValue
===================================================================
15 1 'Actual' 'Net Revenue' 3676798.98999997
15 1 'Actual' 'Total C.S. Salaries' 1463044.72
15 1 'Plan' 'Net Revenue' 3503920.077405
...................... (remaining rows omitted)
然后我们可以像往常一样PIVOT
行来获取新列(这就是它的用途):
SELECT fiscalYear, period, metricName,
[Actual] AS actualValue, [Plan] AS planValue, [PriorYear] AS priorYearValue
FROM <previous_data>
PIVOT (SUM(metricValue) FOR (type IN ([Actual], [Plan], [PriorYear]) pvt
(SUM(...)
实际上不应该在这里做任何事情,因为推测其他列包含一个唯一的行,但我们需要使用聚合函数)
...应该会产生类似于以下内容的内容:
fiscalYear period metricName actualValue planValue priorYearValue
======================================================================================
15 1 'Net Revenue' 3676798.98999997 3503920.077405 40436344.4499999
...................................... (remaining rows omitted)
所以把它放在一起看起来像这样:
SELECT fiscalYear, period, metricName,
[Actual] AS actualValue, [Plan] AS planValue, [PriorYear] AS priorYearValue
FROM (SELECT fiscalYear, period, type, metricName, metricValue
FROM vw_ExecSummary
UNPIVOT (metricValue FOR metricName IN ([Net Revenue], [Total C.S. Salaries])) unpvt) unpvt
PIVOT (SUM(metricValue) FOR type IN ([Actual], [Plan], [PriorYear])) AS pvt
SQL Fiddle Example
不过,我只有一个担心:3676798.98999997
、3503920.077405
等值让我认为这些列是浮点(即REAL
或FLOAT
),但这些值是以货币用途命名的。如果是这种情况......您是知道浮点值不能完全存储像.1
这样的东西,对(即,您实际上不能为值添加一角钱) ?而且,当值变得足够大时,您也不能再添加1
了吗?通常在处理货币值时,您应该使用基于定点类型的东西,例如 DECIMAL
或 NUMERIC
。
【讨论】:
感谢您的解决方案 - 准确!我确实注意到 PIVOT 语句中“类型”一词之前的括号不正确。我删除了它,并在 PIVOT 语句的末尾添加了一个右括号。像魅力一样工作! @Jason - 啊,谢谢。 #更正#。这就是为什么我喜欢先测试它们。那么这两个money列的是的类型是什么? 我相信类型是浮动的(目前不在我的工作笔记本电脑前)。 @Jason - 啊,好吧,向会计解释他们多余的钱从哪里来/从哪里来的很有趣。【参考方案2】:这是Itzig Ben-Gan's cross apply values pivoting的情况:
create table #data (FiscalYear smallint, Period tinyint, ValueType nvarchar(25), NetRevenue float, Salaries float);
insert into #data values
(15,1,N'Actual',3676798.98999,1463044.71999),
(15,1,N'Plan',3503920.977405,1335397.32878),
(15,1,N'PriorYear',4043634.449,1543866.89);
select d.FiscalYear, d.Period,
ActualNetRevenue = sum(v.ActualNetRevenue), ActualSalaries = sum(v.ActualSalaries),
PlanNetRevenue = sum(v.PlanNetRevenue), PlanSalaries = sum(v.PlanSalaries),
PriorYearNetRevenue = sum(v.PriorYearNetRevenue), PriorYearSalaries = sum(v.PriorYearSalaries)
from #data d
cross apply
(values
(N'Actual',d.NetRevenue,d.Salaries,0,0,0,0),
(N'Plan',0,0,d.NetRevenue,d.Salaries,0,0),
(N'PriorYear',0,0,0,0,d.NetRevenue,d.Salaries))
v (ValueType, ActualNetRevenue, ActualSalaries, PlanNetRevenue, PlanSalaries, PriorYearNetRevenue, PriorYearSalaries)
where d.ValueType = v.ValueType
group by d.FiscalYear, d.Period;
drop table #data;
【讨论】:
谢谢,但此示例将所有项目放在一行中。上面的解决方案是我打算做的。以上是关于反透视具有多列的数据 - 请语法帮助的主要内容,如果未能解决你的问题,请参考以下文章