给出一个名为“grade”的表:
STUDENT GRADE
john 94
john 76
john 83
john 87
john 90
我想要一个查询来返回每个学生的几个成绩示例,例如:
STUDENT GRADE1 GRADE2 GRADE3 GRADE4
John 94 76 83 87
请注意,只返回了4个样本成绩列,但该学生的成绩超过4个。
我只知道如何使用GROUP BY子句中的min()和max()函数返回2个示例成绩:
select student, min(grade), max(grade)
from grades
group by student
是否有除min / max以外的任何技巧或功能,使用GROUP BY子句可以显示超过2个等级?
除非它是查询的一部分而不是存储在数据库中,否则我宁愿不编写自己的存储函数来执行此操作。
除了MIN和MAX之外,我正在考虑从记录集中返回其他值的更多函数(如第二高,第三高等)。
想法?
答案 0 :(得分:6)
您可以通过应用row_number()
函数然后应用PIVOT:
select student,
grade1 = [1],
grade2 = [2],
grade3 = [3],
grade4 = [4]
from
(
select student, grade,
row_number() over(partition by student
order by grade desc) seq
from grades
) d
pivot
(
max(grade)
for seq in ([1], [2], [3], [4]) -- the # of grades you want returned
) piv;
PIVOT中使用的新列名称将是您想要返回的等级数。分区中使用的ORDER BY
是grade desc
,但您也可以使用order by newid()
to get a random result being returned。
这也可以使用带有CASE表达式的聚合函数来完成:
select student,
max(case when seq = 1 then grade end) grade1,
max(case when seq = 2 then grade end) grade2,
max(case when seq = 3 then grade end) grade3,
max(case when seq = 4 then grade end) grade4
from
(
select student, grade,
row_number() over(partition by student
order by newid()) seq
from grades
) d
group by student;
答案 1 :(得分:0)
SELECT DISTINCT student,
(
select top 1 grade from
(select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 1
) AS GRADE1 ,
(
select top 1 grade from
(select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 2
) AS GRADE2,
(
select top 1 grade from
(select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 3
) AS GRADE3,
(
select top 1 grade from
(select grade, ROW_NUMBER() OVER(ORDER BY grade DESC) AS Row from grades g2 where g.student = g2.student) a where a.Row = 4
) AS GRADE4
from grades g
使用游标。在此解决方案中,您将获得1到n个结果
DECLARE @grade int
DECLARE @n int
DECLARE @sql varchar(max)
DECLARE _cursor CURSOR FOR
SELECT grade
FROM grade
WHERE student like 'XXX'
OPEN _cursor
FETCH NEXT FROM _cursor INTO @grade
WHILE @@FETCH_STATUS = 0
BEGIN
IF @sql like ''
begin
set @sql = 'SELECT ' + 'XXX' + ' AS Student '
end
set @sql = @sql + ',' + @grade ' as GRADE'+ @n
set @n = @n + 1
END
CLOSE _cursor
DEALLOCATE _cursor
exec(@sql)
此输出将
STUDENT GRADE1 GRADE2 GRADE3 GRADE4
John 94 87 83 76