create table grades ( student varchar(4), assign varchar(4), grade int);
insert into grades values ( 's01','a05',4), ('s01','a06',3),('s02','a04',6),('s02','a05',4),( 's01','a04', 9),( 's02','a01', 9),('s02','a02',8),('s02','a03',9), ( 's01','a01', 9), ( 's01','a02', 7),( 's01','a03', 7) ;
教授保持如上所示的成绩并同意降低两个最低分并取平均分。 向计算机写一个查询,每个学生的平均值如下所示
<SAMPLE_OUTPUT>
+---------+--------------+
| student | avg(O.grade) |
+---------+--------------+
| s01 | 8.0000 |
| s02 | 8.6667 |
+---------+--------------+
答案 0 :(得分:1)
这样做的一种方法是给每个学生的所有成绩一个等级,然后计算某个等级以上成绩的平均值。派生表中的count(*)
用于确保少于三个等级的学生仍然得到平均值(在3个等级的情况下,两个最低等级被淘汰)。
SELECT
a.student,
AVG(CASE
WHEN c > 2 AND rank > 2 THEN grade
WHEN c <= 2 THEN grade
END) avg
FROM (SELECT student, COUNT(*) c FROM grades GROUP BY student) a
JOIN (
SELECT
student,
grade,
(CASE student
WHEN @curType THEN @curRow:=@curRow + 1
ELSE @curRow:=1 AND @curType:=student
END
) + 1 AS rank
FROM
grades p, (SELECT @curRow:=0, @curType:='') r
ORDER BY student , grade ASC
) b ON a.student = b.student
GROUP BY student;
答案 1 :(得分:0)
没有在MySQL中测试,但是应该从这个MSSQL块相对类似(限制而不是顶部,+ 0.0而不是强制转换等) - 我已经为你的表添加了一个ID字段(可以在没有表结构更改的情况下进行复制)使用临时表或WITH..AS语句的预查询:
create table grades (ID INT IDENTITY(1,1), student varchar(4), assign varchar(4), grade int);
insert into grades values ( 's01','a05',4), ('s01','a06',3),('s02','a04',6),('s02','a05',4),( 's01','a04', 9),( 's02','a01', 9),('s02','a02',8),('s02','a03',9), ( 's01','a01', 9), ( 's01','a02', 7),( 's01','a03', 7)
select distinct i.student,
(select avg(cast(ii.grade as float)) from grades ii where ii.id in (
select top (select
case count(*)
when 0 then 0
when 1 then 1
when 2 then 2
else count(*) - 2
end
from grades iii where iii.student= i.student) ii.ID from grades ii where ii.student = i.student order by ii.grade desc))
from grades i
案例陈述是为了确保如果学生有两个或更少的记录,它不会放弃这些成绩 - 对于有三个或更多考试的学生,处理“最差两个被丢弃”的案例系统
如果要求分组,则可以采用不同的方式处理,因为此解决方案不需要分组。
编辑:我正在编辑这个在MySQL中运行,因为这是在MSSQL中,但是另一个答案是在MySQL上工作,所以我只是留在这里用于任何MSSQL窥视同样的问题。
答案 2 :(得分:0)
这是一种方式(但我认为jpw的方法更快)...
SELECT student,MAX(avg_grade) avg_grade
FROM
( SELECT student, AVG(grade) avg_grade FROM grades GROUP BY student
UNION ALL
SELECT a.student
, AVG(grade) avg_grade
FROM grades a
JOIN
( SELECT student
, GROUP_CONCAT(grade ORDER BY grade) grades
FROM grades
GROUP
BY student
) b
ON b.student = a.student
WHERE FIND_IN_SET(a.grade,b.grades) > 2
GROUP
BY student
) x
GROUP
BY student;