将不同的值分隔为列

时间:2017-10-04 12:40:43

标签: sql sql-server

我的数据集看起来像

StudentName | Grading Type | AssignmentName | Grade Given
John Doe    | Exam         | Exam 1         | 90.2
John Doe    | Exam         | Midterm        | 87.0
John Doe    | Homework     | Week 1         | 75.0
John Doe    | Homework     | Week 2         | 100.0
Jane Doe    | Homework     | Week 1         | 100.0
...           ...            ...              ... 

我希望得到每个评分类型的平均成绩作为每个学生的专栏,我该如何解决这个问题?请参阅下面的样本/所需输出

StudentName | Exam | Homework 
John Doe      89.0   88.7
Jane Doe      77.0   100.0

意识到这是我正在讨论的数据集的过度简化,并且案例陈述将涉及超过60个案例,所以我正在寻找实际上基于受控类型将其划分为新列的内容。我确实理解平均功能 - 我希望有一些功能我错过了它的错综复杂功能。任何和所有的帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

使用条件聚合:

select 
    StudentName
  , Exam = avg(case when GradingType = 'Exam' then GradeGiven end)
  , Homework = avg(case when GradingType = 'Homework' then GradeGiven end)
from t
group by StudentName

rextester演示:http://rextester.com/VMB21085

返回:

+-------------+-----------+------------+
| StudentName |   Exam    |  Homework  |
+-------------+-----------+------------+
| Jane Doe    | NULL      | 100.000000 |
| John Doe    | 88.600000 | 87.500000  |
+-------------+-----------+------------+

对于动态pivot()

declare @cols nvarchar(max);
declare @sql  nvarchar(max);
  select @cols = stuff((
    select distinct 
      ', ' + quotename(isnull(nullif(GradingType,''),'unknown'))
      from t 
      order by 1
      for xml path (''), type).value('(./text())[1]','nvarchar(max)')
    ,1,2,'')
select  @sql ='
 select StudentName, ' + @cols +'
  from  (
    select StudentName, GradingType, GradeGiven
      from t
    ) as t
 pivot (avg(GradeGiven) for GradingType in (' + @cols +')) p'
select @sql
exec(@sql);

生成以下代码:

select StudentName, [Exam], [Homework]
  from  (
    select StudentName, GradingType, GradeGiven
      from t
    ) as t
 pivot (avg(GradeGiven) for GradingType in ([Exam], [Homework])) p

并返回:

+-------------+-----------+------------+
| StudentName |   Exam    |  Homework  |
+-------------+-----------+------------+
| Jane Doe    | NULL      | 100.000000 |
| John Doe    | 88.600000 | 87.500000  |
+-------------+-----------+------------+

答案 1 :(得分:1)

你可以使用它。

SELECT * FROM
    (SELECT StudentName, [Grading Type], [Grade Given] FROM MyTable) SRC
    PIVOT( AVG( [Grade Given] ) FOR [Grading Type] IN ([Exam],[Homework])) PVT

答案 2 :(得分:0)

您可以使用PIVOT命令执行此操作。

这样的事情应该达到你想要的......

DROP TABLE IF EXISTS dbo.Schoolwork;
CREATE TABLE dbo.Schoolwork
(StudentName varchar(128), GradingType varchar(30), AssignmentName varchar(30), GradeGiven decimal(4,1));
INSERT dbo.Schoolwork (StudentName,GradingType,AssignmentName,GradeGiven)
VALUES 
('John Doe','Exam','Exam 1',90.2 ),
('John Doe','Exam','Midterm',87.0 ),
('Jane Doe','Exam','Exam 1',77.0 ),
('John Doe','Homework','Week 1',75.0 ),
('John Doe','Homework','Week 2',100.0),
('Jane Doe','Homework','Week 1',100.0);

SELECT * 
FROM (
        SELECT s.StudentName,
               s.GradingType,
               s.GradeGiven 
        FROM dbo.Schoolwork AS s
      ) AS src
      PIVOT (avg(src.GradeGiven) FOR GradingType IN ([Exam],[Homework])
      ) AS pvt;

(我冒昧地将Jane Doe的考试成绩添加到测试数据中)。

相关问题