[CareerCup] 15.7 Student Grade 学生成绩

15.7 Imagine a simple database storing information for students‘ grades. Design what this database might look like and provide a SQL query to return a list of the honor roll students (top 10%), sorted by their grade point average.

在一个简化的数据库中我们有三个表,Students表,Courses表和CourseEnrollment表如下:

TABLE Students

+-------------+-------------+
| Students                  |
+-------------+-------------+
| StudentID   | int(11)     |
| StudentName | varchar(30) |
| Address     | varchar(50) |
+-------------+-------------+

TABLE Courses

+-------------+-------------+
| Courses                   |
+-------------+-------------+
| CourseID    | int(11)     |
| CourseName  | varchar(30) |
| ProfessorID | int(11)     |
+-------------+-------------+

TABLE CourseEnrollment

+-----------+---------+
| CourseEnrollment    |
+-----------+---------+
| CourseID  | int(11) |
| StudentID | int(11) |
| Grade     | float   |
| Term      | int(11) |
+-----------+---------+

使用SQL Server的Top .. Percent 函数可以如下代码:

-- SQL Server (Incorrect Code)
SELECT TOP 10 PERCENT AVG(CourseEnrollment.Grade) AS GPA, CourseEnrollment.StudentID
FROM CourseEnrollment GROUP BY CourseEnrollment.StudentID ORDER BY AVG(CourseEnrollment.Grade);

由于我使用的是MySQL,本来可以用Limit关键字来做,但是MySQL的Limit关键字后面只能为常量,不能为变量,所以只能换一种写法,所以代码如下:

SET @limit = (SELECT 0.1 * COUNT(*) FROM CourseEnrollment);
SELECT Grade FROM (
SELECT *, @rownum := @rownum + 1 AS rank
FROM CourseEnrollment, (SELECT @rownum := 0) init ORDER BY Grade DESC
) d WHERE rank <= @limit ;

但是上面的写法确实返回了top 10%的行,但是假如我们有100个学生,前15个学生都是4.0的GPA,而上面的方法只能返回10个学生,而我们需要返回那15个都是4.0的学生,所以为了实现这个,我们可以这么做:

-- SQL Server
DECLARE @GPACutOff FLOAT;
SET @GPACutOff = (SELECT MIN(GPA) AS ‘GPAMin‘ FROM (
SELECT TOP 10 PERCENT AVG(CourseEnrollment.Grade) AS GPA, FROM CourseEnrollment
GROUP BY CourseEnrollment.StudentID ORDER BY GPA DESC) Grades);

SELECT StudentName, GPA FROM (
SELECT AVG(CourseEnrollment.Grade) AS GPA, CourseEnrollment.StudentID
FROM CourseEnrollment GROUP BY CourseEnrollment.StudentID
HAVING AVG(CourseEnrollment.Grade) >= @GPACutOff) Honors
INNER JOIN Students ON Honors.StudentID = Students.StudentID;

上面的方法先定义了一个GPACutOff变量,算出了前10%的GPA,然后在后面的代码中遍历所有的GPA,返回所有大于等于GPACutOff的行。而是用MySQL可以写出实现同样功能的代码,参考了我之前的博客Department Top Three SalariesDepartment Highest SalarySecond Highest Salary,用更简洁的方式如下:

-- MySQL
SELECT c.Grade FROM CourseEnrollment c WHERE (SELECT COUNT(DISTINCT Grade) FROM CourseEnrollment
WHERE Grade > c.Grade) < (SELECT 0.1 * COUNT(*) FROM CourseEnrollment) ORDER BY c.Grade DESC;

要注意那些潜在的假设,比如看上面的设计,一个潜在的假设就是每门课只能由一个教授交,而在一些学校,课程可能被多个教授交。但是,我们需要做一些假设,而潜在的一些不正确的假设需要多加注意。

我们需要在灵活性和复杂性之间做出平衡,比如设计一个课程可以被多个教授交的系统是增加了灵活性,但是也增加了复杂度,如果我们的系统对于任何情况都适用,那么系统就会无比的复杂。所以我们需要设计出一个相对灵活的系统,但仍然有假设和限定,这不仅需要数据库设计的知识,还包括了面向对象的设计。

CareerCup All in One 题目汇总

时间: 2024-12-16 09:24:04

[CareerCup] 15.7 Student Grade 学生成绩的相关文章

C++习题 对象转换(定义一个Teacher(教师)类(教师号,姓名,性别,薪金)和一个Student(学生)类(学号,姓名,性别,成绩)编写程序,将一个Student对象(学生)转换为Teacher(教师)类。

Description 定义一个Teacher(教师)类(教师号,姓名,性别,薪金)和一个Student(学生)类(学号,姓名,性别,成绩),二者有一部分数据成员是相同的,num(号码),name(姓名),sex(性别).编写程序,将一个Student对象(学生)转换为Teacher(教师)类,只将以上3个相同的数据成员移植过去.可以设想为: 一位学生大学毕业了,留校担任教师,他原有的部分数据对现在的教师身份来说仍然是有用的,应当保留并成为其教师数据的一部分. Input 一个教师的信息和一个学

15周【项目1-用二进制文件处理学生成绩】

问题描述: [项目1-用二进制文件处理学生成绩] (1)定义学生类,其中包含学号.姓名.C++课.高数和英语成绩及总分数据成员,成员函数根据需要确定. (2)读入学生的成绩,并求出总分,用对象数组进行存储.ASCII文件score.dat中保存的是100名学生的学号.姓名和C++课.高数和英语成绩. (3)将所有数据保存到一个二进制文件binary_score.dat中,最后通过键盘输入你的信息,并写入到文件中(咱不谦虚,三科全100分,期末求好运). (4)为验证输出文件正确,再将binary

简易学生成绩管理管理系统(java描述)

没正式学过java,但是系统学过C++后,初略的看了下java的基本语法,于是我就尝试着用java来写个简单的学生管理系统,功能不齐全,以后有空再补充吧. 写的时候定义了不同的包名字,如jeaven1 , jeaven2 , jeaven3 先上Student类: 1 package jeaven1; 2 import java.io.*; 3 4 public class Student 5 { 6 private String name; 7 private String id; 8 pri

学生成绩管理程序(C语言dos程序)

在昨天写的一个血生成绩管理程序 给大家分享一下 本程序仅供学习交流 代码如下: 1 /*本程序为简单的学生信息管理系统,作为技术交流,并不作为其它用途*/ 2 #include<stdio.h> 3 #include<string.h> 4 5 void rank1(float b[]); 6 int count = 1; 7 //结构体 8 struct student 9 { 10 char name[10]; //学生的姓名 11 char subject[10]; //学生

学生成绩管理C语言版

[标题]学生成绩管理的设计与实现 [开发语言]C语言 [概要设计]使用结构体存储学生的学号.姓名和成绩信息,实现对学生成绩类的基本操作:增加.删除.查询.排序 [测试数据]按提示输入5组正确的正确的数据和5组有问题的数据,查看程序能否运行正确 [测试结果]基本功能运行正确,异常输入无法处理(关于性能对比测试,查看C++版:http://www.cnblogs.com/forerve/p/3908716.html) [详细设计] 1 #include<stdio.h> 2 #include<

学生成绩管理系统

编写语言:c++ 代码如下: main.cpp 1 #include <iostream> 2 #include <cstdio> 3 #include<stdlib.h> 4 #include <cstring> 5 #include <windows.h> 6 #include "see3.cpp" 7 #include "see4.cpp" 8 #include "jie gou.cpp&q

学生——成绩表2.1

一.表说明(MYSql) 二.导入测试数据 学生表 insert into Student values('01' , N'赵雷' , '1990-01-01' , N'男'); insert into Student values('02' , N'钱电' , '1990-12-21' , N'男'); insert into Student values('03' , N'孙风' , '1990-05-20' , N'男'); insert into Student values('04'

添加学生成绩(对象数组的传递)

1 package Texts.News.copy; 2 /* 3 * 测试类,在这里运行 4 */ 5 public class Main { 6 7 public static void main(String[] args) { 8 9 IS is = new IS(); //创建学生操作对象 10 Student[] n = is.input(); //接返回的对象数组 11 12 System.out.println("\n 学生信息"); 13 System.out.pri

IO流的练习4 —— 键盘录入学生成绩信息,进行排序后存入文本中

需求: 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件 分析: A:创建学生类 B:创建集合对象 TreeSet<Student> C:键盘录入学生信息存储到集合 D:遍历集合,把数据写到文本文件 首先创建个学生类 1 package zl_Test; 2 /** 3 * 这是个记录学生成绩类 4 * @author LZL 5 * 6 */ 7 public class Student { 8 private String name; 9 priva