Sql server 使用pivot将列转换为行

Sql server 使用pivot将列转换为行,sql-server,stored-procedures,Sql Server,Stored Procedures,我想将列转换为行,以适应图像中的格式 这是我的疑问: Select dt1.Year,dt1.oneyearret as '1-Year Retention',dt2.twoyearret as '2-Year Retention',dt4.fouryeargrad as '4-Year Graduation Rate',dt5.fiveyeargrad as '5-Year Graduation Rate',dt6.sixyeargrad as '6-Year Graduation Rate'

我想将列转换为行,以适应图像中的格式 这是我的疑问:

Select dt1.Year,dt1.oneyearret as '1-Year Retention',dt2.twoyearret as '2-Year Retention',dt4.fouryeargrad as '4-Year Graduation Rate',dt5.fiveyeargrad as '5-Year Graduation Rate',dt6.sixyeargrad as '6-Year Graduation Rate' from
(select case WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2015' then '2015' WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2016' then '2016' else (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)))  end  as 'Year',
                                  cast(convert(varchar,(Convert(Money,SUM(rg.RET1_FF),1)/Convert(Money,SUM(rg.COHORT_COUNT),1))*100,1) as numeric(10,1)) as oneyearret         
                                  from vw_Retention_Graduation_F rg
                                  inner join dim_Time t
                                  on rg.TIME_KEY = t.TIME_KEY
                                  inner join dim_Part_Full pf
                                  on rg.PART_FULL_KEY=pf.PART_FULL_KEY
                                  inner join dim_Student_Level sl
                                  on rg.STUDENT_LEVEL_KEY=SL.STUDENT_LEVEL_KEY
                                  inner join dim_Student_Population sp
                                  on rg.STUDENT_POPULATION_KEY=sp.STUDENT_POPULATION_KEY
                                  inner join dim_College c
                                  on rg.COLLEGE_KEY = c.COLLEGE_KEY
                                  WHERE t.ACADEMIC_PERIOD between 201527 and 201627
                                  AND pf.PART_FULL = 'F'
                                  AND sl.STUDENT_LEVEL = 'UG'
                                  AND sp.STUDENT_POPULATION = 'N'
                                  GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)) ) ) dt1 inner join
(select case WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2014' then '2015' WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2015' then '2016' else (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)))  end  as 'Year',
                                  cast(convert(varchar,(Convert(Money,SUM(rg.RET2_FF),1)/Convert(Money,SUM(rg.COHORT_COUNT),1))*100,1) as numeric(10,1)) as twoyearret         
                                  from vw_Retention_Graduation_F rg
                                  inner join dim_Time t
                                  on rg.TIME_KEY = t.TIME_KEY
                                  inner join dim_Part_Full pf
                                  on rg.PART_FULL_KEY=pf.PART_FULL_KEY
                                  inner join dim_Student_Level sl
                                  on rg.STUDENT_LEVEL_KEY=SL.STUDENT_LEVEL_KEY
                                  inner join dim_Student_Population sp
                                  on rg.STUDENT_POPULATION_KEY=sp.STUDENT_POPULATION_KEY
                                  inner join dim_College c
                                  on rg.COLLEGE_KEY = c.COLLEGE_KEY
                                  WHERE t.ACADEMIC_PERIOD between 201427 and 201527
                                  AND pf.PART_FULL = 'F'
                                  AND sl.STUDENT_LEVEL = 'UG'
                                  AND sp.STUDENT_POPULATION = 'N'
                                  GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)) ) ) dt2 on dt1.Year = dt2.year
                                  inner join
(select case WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2012' then '2015' WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2013' then '2016' else (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)))  end  as 'Year',
                                  cast(convert(varchar,(Convert(Money,SUM(rg.GRAD4_FF),1)/Convert(Money,SUM(rg.COHORT_COUNT),1))*100,1) as numeric(10,1)) as fouryeargrad         
                                  from vw_Retention_Graduation_F rg
                                  inner join dim_Time t
                                  on rg.TIME_KEY = t.TIME_KEY
                                  inner join dim_Part_Full pf
                                  on rg.PART_FULL_KEY=pf.PART_FULL_KEY
                                  inner join dim_Student_Level sl
                                  on rg.STUDENT_LEVEL_KEY=SL.STUDENT_LEVEL_KEY
                                  inner join dim_Student_Population sp
                                  on rg.STUDENT_POPULATION_KEY=sp.STUDENT_POPULATION_KEY
                                  inner join dim_College c
                                  on rg.COLLEGE_KEY = c.COLLEGE_KEY
                                  WHERE t.ACADEMIC_PERIOD between 201227 and 201327
                                  AND pf.PART_FULL = 'F'
                                  AND sl.STUDENT_LEVEL = 'UG'
                                  AND sp.STUDENT_POPULATION = 'N'
                                  GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)) ) ) dt4 on dt2.Year = dt4.year
                                  inner join
(select case WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2011' then '2015' WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2012' then '2016' else (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)))  end  as 'Year',
                                  cast(convert(varchar,(Convert(Money,SUM(rg.GRAD5_FF),1)/Convert(Money,SUM(rg.COHORT_COUNT),1))*100,1) as numeric(10,1)) as fiveyeargrad        
                                  from vw_Retention_Graduation_F rg
                                  inner join dim_Time t
                                  on rg.TIME_KEY = t.TIME_KEY
                                  inner join dim_Part_Full pf
                                  on rg.PART_FULL_KEY=pf.PART_FULL_KEY
                                  inner join dim_Student_Level sl
                                  on rg.STUDENT_LEVEL_KEY=SL.STUDENT_LEVEL_KEY
                                  inner join dim_Student_Population sp
                                  on rg.STUDENT_POPULATION_KEY=sp.STUDENT_POPULATION_KEY
                                  inner join dim_College c
                                  on rg.COLLEGE_KEY = c.COLLEGE_KEY
                                  WHERE t.ACADEMIC_PERIOD between 201127 and 201227
                                  AND pf.PART_FULL = 'F'
                                  AND sl.STUDENT_LEVEL = 'UG'
                                  AND sp.STUDENT_POPULATION = 'N'
                                  GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)) ) ) dt5 on dt4.Year = dt5.year
                                  inner join
(select case WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2010' then '2015' WHEN (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4))) ='2011' then '2016' else (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)))  end  as 'Year',
                                  cast(convert(varchar,(Convert(Money,SUM(rg.GRAD6_FF),1)/Convert(Money,SUM(rg.COHORT_COUNT),1))*100,1) as numeric(10,1)) as sixyeargrad         
                                  from vw_Retention_Graduation_F rg
                                  inner join dim_Time t
                                  on rg.TIME_KEY = t.TIME_KEY
                                  inner join dim_Part_Full pf
                                  on rg.PART_FULL_KEY=pf.PART_FULL_KEY
                                  inner join dim_Student_Level sl
                                  on rg.STUDENT_LEVEL_KEY=SL.STUDENT_LEVEL_KEY
                                  inner join dim_Student_Population sp
                                  on rg.STUDENT_POPULATION_KEY=sp.STUDENT_POPULATION_KEY
                                  inner join dim_College c
                                  on rg.COLLEGE_KEY = c.COLLEGE_KEY
                                  WHERE t.ACADEMIC_PERIOD between 201027 and 201127
                                  AND pf.PART_FULL = 'F'
                                  AND sl.STUDENT_LEVEL = 'UG'
                                  AND sp.STUDENT_POPULATION = 'N'
                                  GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD_all,1,4)) ) )  dt6 on dt5.Year = dt6.year 
电流输出:

所需输出:

在将冗长的SQL代码替换为较短的SQL代码后,只需生成示例数据,即可通过以下方式实现实际的“转置”操作:

create table tbl (yr int, y1ret float, y2ret float, y4grad float, y5grad float, y6grad float);
insert into tbl VALUES (2015, 83.5, 71.4, 34.8, 54.7, 59.9 ), (2016, 83.6, 73.8, 33.8, 53.6, 60);

select * from (
  select yr, col, value
  from tbl
  unpivot
  (
    value
    for col in (y1ret, y2ret, y4grad, y5grad, y6grad)
  ) unpiv

) src
pivot
(
  max(value)
  for yr in ([2015], [2016])
) piv
这当然是对此处介绍的原始解决方案的改编:
可以在此处找到正在运行的演示:

在大多数应用程序中,在接收环境中执行此类操作更简单、更快,即在后端使用PHP或在前端使用JavaScript

编辑

要将冗长的SQL代码融入其中,您可以执行以下操作:

;WITH tbl AS ( -- YOUR CODE GOES HERE --
)
select * from (
  select yr, col, value
  from tbl
  unpivot
  (
    value
    for col in (y1ret, y2ret, y4grad, y5grad, y6grad)
  ) unpiv

) src
pivot
(
  max(value)
  for yr in ([2015], [2016])
) piv

哇,这个问题真难看。如果你能读得好的话,或者不用麻烦。所以我帮你格式化你的文章,你告诉我不要麻烦。对于那些试图帮助你的人来说,这不是一种很好的态度。也许这对你有一些帮助?哦,我感觉没有多少人会打扰你,特别是像@SeanLange和我这样的人。谢谢你,但是我没有创建表的权限。你不需要创建表。那只是一个占位符。如果您将代码放入一个“公共表表达式”,那么您就可以从那里运行整个过程。“CTE”的行为就像一个视图或一个表。啊,明白了!非常感谢!col和value在这里代表什么?它们是您可以自己选择的名称,并且是
unpivot
子句的一部分。您需要先生成此中间格式,然后才能使用
pivot
再次将其缝合在一起,请参见此处或此处: