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