sql - 如何让查询返回行值的样本作为列?

标签 sql sql-server

给定一个名为“grades”的表:

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 之外,还可以从记录集中返回其他值(例如第二高、第三高等)。

想法?

最佳答案

您可以通过应用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;

参见SQL Fiddle with Demo .

数据透视表中使用的新列名称将是您想要返回的成绩数。分区中使用的 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;

参见SQL Fiddle with Demo

关于sql - 如何让查询返回行值的样本作为列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19664313/

相关文章:

sql - 串联 - T-SQL

java - Java中order by子句的SQL注入(inject)漏洞

sql - 如何获取自引用表的每条记录的所有子项

sql - 复合主键自动递增

php - mysqli 的错误实现?

php - Metaphone vs Levenshtein vs Soundex vs Hamming

sql - @@IDENTITY、SCOPE_IDENTITY()、OUTPUT 和其他检索最后身份的方法

sql-server - 在 Azure SQL 数据库中查找“管理”按钮

sql-server - 将 db_denydatawriter 角色分配给用户 dbo

c# - 无法从 Visual Studio 2013 连接到远程 SQL 服务器上的数据库