Sql 在一个值上透视一个表,但将一行上的数据按另一行分组?
我的桌子Sql 在一个值上透视一个表,但将一行上的数据按另一行分组?,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我的桌子 CREATE TABLE #table ([Indicator] int, [Scenario_code] smallint, [period] nvarchar(50), [Value] int, [AREA code] nvarchar(10), [Release_Code] int) ; INSERT INTO #table ([Indicator], [Scenario_code], [period], [Value], [AREA code], [R
CREATE TABLE #table
([Indicator] int, [Scenario_code] smallint, [period] nvarchar(50), [Value] int, [AREA code] nvarchar(10), [Release_Code] int)
;
INSERT INTO #table
([Indicator], [Scenario_code], [period], [Value], [AREA code], [Release_Code])
VALUES
(2, 7, '2000-06-13', 1000, 'OP014', 17),
(2, 16, '2000-09-12', 1100, 'OP014', 17),
(2, 17, '2002-06-22', 1200, 'OP014', 17),
(3, 7, '2000-01-12', 1300, 'OP014', 17),
(3, 16, '2000-06-17', 500, 'OP014', 17),
(3, 17, '2008-05-04', 550, 'OP014', 17),
(4, 7, '2000-06-12', 600, 'OP014', 17),
(4, 16, '2000-12-12', 650, 'OP014', 17),
(4, 17, '2013-06-12', 150, 'OP014', 17)
我希望字段[period]和[Value]以某种方式根据其[indicator]和[scenario_code]字段进行旋转。有三个指标值(2,3,4)和三个情景代码(7,16,17)。我希望按场景代码对行进行分组,并将每个对应的指示符值作为自己的字段。结果是三行,应该是这样的
{[Scernario_代码]、[Period 2]、[Value 2]、[Period 3]、[Value 3]、[Period 4]、[Value 4]、[Area code]、[Release code]}
7,'2000-06-13',1000,'2000-01-12',1300,'2000-06-12',600,'OP014',17
16,'2000-09-12',1100,'2000-06-17',500,'2000-12-12',650,'OP014',17
17,'2002-06-22',1200,'2008-05-04',550,'2013-06-12',150,'OP014',17
根据绑定到一个[方案\代码]的三个指标值(2,3,4),周期和值列已分布。我已经用它所依赖的指示符值为这些列添加了后缀。理想情况下,我会将它们别名为其他东西
思想
这显然是尖叫的枢轴或un枢轴(甚至两者),但我的教科书没有什么东西,我需要考虑两个列的扩展元素[Value]和[Value]。我需要按指标值旋转数据,使它们成为列,但与场景代码分组在同一行上。也许串联会有帮助
我见过交叉应用的枢轴,看起来很有希望,但我还不能让它工作,因为我不完全理解如何利用它。我最近开始使用SQL Server 2012。试试这个;with CTE as
(select *,ROW_NUMBER()over(partition by Scenario_code order by period)rn from #table)
select distinct a.Scenario_code, b.period [period2],b.Value [Value2],c.period [period3],c.Value [Value3],d.period [period4],d.Value [Value4]
from CTE a left join CTE b on a.Scenario_code=b.Scenario_code and b.rn=1
left join CTE c on a.Scenario_code=c.Scenario_code and c.rn=2
left join CTE d on a.Scenario_code=d.Scenario_code and d.rn=3
drop table #table
检查最新的,然后我没有注意到指示灯
Select * from
(select ROW_NUMBER()over(partition by a.Scenario_code order by a.Scenario_code)rn , a.Scenario_code, b.period [period2],b.Value [Value2],c.period [period3],c.Value [Value3],d.period [period4],d.Value [Value4]
from #table a left join #table b on a.Scenario_code=b.Scenario_code and b.indicator=3
left join #table c on a.Scenario_code=c.Scenario_code and c.indicator=4
left join #table d on a.Scenario_code=d.Scenario_code and d.indicator=2
)t4 where rn=1
获取结果的最简单方法是使用带有CASE表达式的聚合函数:
select
scenario_code,
max(case when indicator = 2 then period end) [Period 2],
max(case when indicator = 2 then value end) [Value 2],
max(case when indicator = 3 then period end) [Period 3],
max(case when indicator = 3 then value end) [Value 3],
max(case when indicator = 4 then period end) [Period 4],
max(case when indicator = 4 then value end) [Value 4],
[area code],
Release_Code
from yourtable
group by scenario_code, [area code], Release_Code
看
但是您可以使用PIVOT函数来获得结果,但是您还需要首先取消PIVOT期间
和值
列,因为您希望在两列上进行轴心
由于您使用的是SQL Server 2012,因此可以使用带值的交叉应用来取消PIVOT。基本语法为:
select scenario_code, [area code], release_code,
col = col +' ' +cast(indicator as varchar(10)),
val
from yourtable
cross apply
(
values
('Period', convert(varchar(10), period, 120)),
('Value', convert(varchar(10), value))
) c (col, val);
看。这将使您的数据转换为以下格式:
| SCENARIO_CODE | AREA CODE | RELEASE_CODE | COL | VAL |
|---------------|-----------|--------------|----------|------------|
| 7 | OP014 | 17 | Period 2 | 2000-06-13 |
| 7 | OP014 | 17 | Value 2 | 1000 |
| 16 | OP014 | 17 | Period 2 | 2000-09-12 |
| 16 | OP014 | 17 | Value 2 | 1100 |
您会注意到,我们必须将这两个列强制转换为相同的数据类型,才能使这个取消激励过程正常工作。一旦数据被解压,您就可以轻松地应用PIVOT函数并将COL
中的值转换为新的列标题:
select scenario_code,
[Period 2], [Value 2],
[Period 3], [Value 3],
[Period 4], [Value 4],
[area code], release_code
from
(
select scenario_code, [area code], release_code,
col = col +' ' +cast(indicator as varchar(10)),
val
from yourtable
cross apply
(
values
('Period', convert(varchar(10), period, 120)),
('Value', convert(varchar(10), value))
) c (col, val)
) d
pivot
(
max(val)
for col in ([Period 2], [Value 2],
[Period 3], [Value 3],
[Period 4], [Value 4])
) piv;
看。两个版本的最终结果如下:
| SCENARIO_CODE | PERIOD 2 | VALUE 2 | PERIOD 3 | VALUE 3 | PERIOD 4 | VALUE 4 | AREA CODE | RELEASE_CODE |
|---------------|------------|---------|------------|---------|------------|---------|-----------|--------------|
| 7 | 2000-06-13 | 1000 | 2000-01-12 | 1300 | 2000-06-12 | 600 | OP014 | 17 |
| 16 | 2000-09-12 | 1100 | 2000-06-17 | 500 | 2000-12-12 | 650 | OP014 | 17 |
| 17 | 2002-06-22 | 1200 | 2008-05-04 | 550 | 2013-06-12 | 150 | OP014 | 17 |
对于
period
字段,您总是有三个日期吗?不总是,我的[period]和[value]字段可以有空值,我很高兴在我的列中有空值。但是如果您考虑col count,那么对应的场景代码将始终有三个[period]字段和三个[value]字段。遗憾的是,它们是价值观,我已经看到了一些出色的groovy self-join回答,我能问一下你是如何看待其中的逻辑的吗?我不会把这当作一种选择。有没有办法不使用DISTINCT?只要比较一下表,[Values]和[Period]字段被排序,DISTINCT被删除,做得很好,这就是我需要的答案。谢谢你@kumarHarsh