Sql 如何让查询以列的形式返回行值的样本?

Sql 如何让查询以列的形式返回行值的样本?,sql,sql-server,Sql,Sql Server,给出一个名为“等级”的表格: 我希望查询返回每个学生的几个分数示例,例如: STUDENT GRADE1 GRADE2 GRADE3 GRADE4 John 94 76 83 87 请注意,只返回了4个示例成绩列,但该学生的成绩超过4个 我只知道如何在GROUPBY子句中使用min()和max()函数返回2个示例等级: select student, min(grade), max(grade) from grades group b

给出一个名为“等级”的表格:

我希望查询返回每个学生的几个分数示例,例如:

STUDENT    GRADE1  GRADE2   GRADE3  GRADE4
John       94      76       83      87
请注意,只返回了4个示例成绩列,但该学生的成绩超过4个

我只知道如何在GROUPBY子句中使用min()和max()函数返回2个示例等级:

select student, min(grade), max(grade) 
from grades
group by student
除min/max外,是否有任何技巧或功能可以使用GROUP BY子句仅显示2个以上的等级

我不希望编写自己的存储函数来实现这一点,除非它是查询的一部分,而不是存储在数据库中

我正在考虑更多的函数,它们从记录集中返回除最小值和最大值以外的其他值(如第二高、第三高等)


想法?

我提出这样的建议。唯一的限制是不能显示示例1到n,只能显示确定的数量

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

您可以通过应用
row\u number()
函数,然后应用枢轴来获得结果:

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;

数据透视中使用的新列名将是您希望返回的分数。分区中使用的
ORDER BY
是BY
grade desc
,但您也可以查看使用

这也可以通过使用带有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;

请参见

是否有一列指示哪一列是第一列、第二列。。。分数?@juergend如果我理解正确,我相信他想选择一个预设数量的随机行(本例中为4行)进行抽样。学生的最高分数是多少?看看Pivot有点复杂。。。在使用临时表之前,我已经获得了相同的结果。。。您是否愿意使用临时表格解决方案?其他可能的解决方案是使用游标非常好。你知道这项技术应用于甲骨文有多容易吗?@Federico使用游标是个好主意吗?这个答案不是真正可伸缩的。@请检查它没有编译的查询语法——您不能引用筛选器中的
列,因为它还不存在
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;