Pivot a table on a value but group the data on one line by another?

后端 未结 2 815
野趣味
野趣味 2020-12-21 23:30

My table

CREATE TABLE #table
    ([Indicator] int, [Scenario_code] smallint, [period] nvarchar(50), [Value] int, [AREA code] nvarchar(10), [Release_Code] int)         


        
相关标签:
2条回答
  • 2020-12-21 23:50

    The simplest way to get the result would be using an aggregate function with a CASE expression:

    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
    

    See SQL Fiddle with Demo

    But you can use the PIVOT function to get the result but you would also need to unpivot the Period and Value columns first, since you want to pivot on two columns.

    Since you are using SQL Server 2012 you can use CROSS APPLY with VALUES to unpivot. The basic syntax will be:

    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);
    

    See SQL Fiddle with Demo. This is going to get your data into the format:

    | 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 |
    

    You'll notice that we had to cast/convert both columns to the same datatype in order for this unpivoting process to work. Once the data has been unpivoted, then you can easily apply the PIVOT function and convert your values in COL to the new column headers:

    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;
    

    See SQL Fiddle with Demo. Both versions give a final result of:

    | 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 |
    
    0 讨论(0)
  • 2020-12-22 00:04

    try this,

    ;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 
    

    Check Latest,then i didn't notice indicator

    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
    
    0 讨论(0)
提交回复
热议问题