写本篇前 首先非常感谢的两位CSDN上的朋友是:
echiynn(寶琲)和
zhazhaok(喳喳)
本人工作中遇到一张比较复杂的表,数据大约几百万条,由于涉及到工作机密,暂时以下面的数据来说明我要处理的问题。
数据库中scorenew表中有如下数据:记录了一个学校比较乱的学生成绩记录,每个学生对应不同的课程,一个课程又至少有两个老师,在2006年里考试不及格的同学(result='F'),可在2007年补考,若补考过了则该学生该门课程是认为合格的(如2002101),也可以在2006考试虽然是及格,但由于分数刚好60,也允许同学补考,但补考成绩不及格则被认为该生课程是不合格的(如2002102也就是对同一个学生ID,课程成绩以该门课程考试时间最大的那个为准).
学号
课程名
老师
考试结果
考试日期 班级
studentid
classname classteacher result testdate banji
2002100
数学
B2老师
P 2006-7-3 1
2002100
外语
C1老师
P 2006-7-5 1
2002100
语文
A1老师
P 2006-7-1 1
2002101
数学
B2老师
P 2006-7-3 1
2002101
语文
A1老师
F 2006-7-1 1
2002101
语文
A1老师
P 2007-7-1 1
2002102
数学
B1老师
P 2006-7-3 2
2002102
数学
B1老师
F 2007-7-3 2
2002102
外语
C1老师
P 2006-7-5 2
2002102
语文
A1老师
F 2006-7-1 2
2002102
语文
A1老师
F 2007-7-1 2
2002103
数学
B1老师
P 2006-7-3 2
2002103
外语
C2老师
P 2006-7-5 2
2002103
语文
A2老师
P 2007-7-1 2
2002104
数学
B2老师
P 2006-7-3 1
2002104
外语
C1老师
F 2006-7-5 1
2002104
外语
C1老师
P 2007-7-5 1
2002104
语文
A2老师
P 2006-7-1 1
.现在求下面几个SQL语句:
1.求所有科目都及格的人数
1.1.先求出总人数
SELECT COUNT(DISTINCT studentid) AS 总人数 FROM scorenew
结果=5
1.2.再求出考试科目最终有不及格的个数。
SELECT STUDENTID, Result
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM SCORENEW t
WHERE NOT EXISTS
(SELECT 1
FROM SCORENEW
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate)) a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')
结果显示
2002102
F
改成如下语句
SELECT COUNT(DISTINCT STUDENTID) AS 不及格人数
FROM (SELECT STUDENTID, Result
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM SCORENEW t
WHERE NOT EXISTS
(SELECT 1
FROM SCORENEW
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate))
a
GROUP BY STUDENTID, Result
HAVING (Result = 'F'))
显示:
不及格人数
1
所以合格人数=5-1=4
2.求参加某门科目的人数和该门科目及格的人数.
以科目数学为例:
第一步:先求出参加该门课程的总人数
SELECT COUNT(DISTINCT studentid) AS 该科目总人数
FROM scorenew
WHERE (classname = '数学')
结果显示为5
第二步:
SELECT STUDENTID, Result
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM SCORENEW t
WHERE NOT EXISTS
(SELECT 1
FROM SCORENEW
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classname = '数学') a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')
显示结果
2002102 F
改写成统计该科目不及格人数
SELECT COUNT(DISTINCT STUDENTID) AS 该科目不及格人数
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM SCORENEW t
WHERE NOT EXISTS
(SELECT 1
FROM SCORENEW
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classname = '数学') a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')
该科目不及格人数
1
或者求科目是数学的所有成绩记录:
SELECT *
FROM scorenew
WHERE (classname = '数学')
ORDER BY studentid, testdate
同理求某个老师下面不及格的人数
SELECT COUNT(DISTINCT STUDENTID) AS 该老师下不及格人数
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, classteacher
FROM SCORENEW t
WHERE NOT EXISTS
(SELECT 1
FROM SCORENEW
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classteacher = 'B2老师') a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')
3.求2006年度所有科目都及格的人数,即一次性考试通过的人数.
第一步:先求出2006的所有考试记录
SELECT * FROM scorenew WHERE (testdate < '2007')
(因为本数据中只有2006和2007年的数据)
为2006年的成绩创造个视图
CREATE VIEW v_score2006 AS SELECT studentid, classname, classteacher, result,
testdate, banji
FROM scorenew
WHERE (testdate < '2007')
查看视图创建是否成功
SELECT * FROM v_score2006 ORDER BY studentid, testdate
再根据上面的视图进行查找
SELECT STUDENTID, Result
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate)) a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')
查找结果:
Studentid result
2002101
F
2002102
P
2002104
F
改写成统计上面的个数
SELECT COUNT(DISTINCT STUDENTID) AS 该年不及格人数
FROM (SELECT STUDENTID, Result
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate))
a
GROUP BY STUDENTID, Result
HAVING (Result = 'F')) DERIVEDTBL
结果显示:
该年不及格人数:
3
统计该年具体科目不及格人数
以语文为例子
//绿色标记的要对称
SELECT
STUDENTID, Result, CLASSNAME, TestDate
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classname = '语文') a
GROUP BY
STUDENTID, Result, CLASSNAME, TestDate
HAVING (Result = 'F')
显示结果:
2002101 F
语文 2006-7-1
2002102 F
语文 2006-7-1
或者连班级也显示在内可用下面的语句
SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classname = '语文') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')
显示结果:
2002101 F
语文 2006-7-1
1
2002102 F
语文 2006-7-1
2
改写成统计个数的语句
SELECT COUNT(DISTINCT STUDENTID) AS 该年该科目不及格人数
FROM (SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
classname = '语文') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F'))
显示结果:
该年该科目不及格人数
2
求该年该班级不及格的人数
SELECT
STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT
STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
banji = '1') a
GROUP BY
STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')
显示结果:
2002101 F 语文
2006-7-1 1
2002104 F 外语
2006-7-5 1
改写成统计结果
: SELECT COUNT(DISTINCT STUDENTID) AS 该年该班级不及格人数
FROM (SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
banji = '1') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F'))
显示结果:
该年该班级不及格人数:
2
查找该年该班级某个科目不及格人数
以1班语文成绩为例
SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
banji = '1' AND classname = '语文') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')
显示结果:
2002101
F
语文
2006-7-1 1
改写成统计结果:
SELECT COUNT(DISTINCT STUDENTID) AS 该年该班该科目不及格人数
FROM (SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006 t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
banji = '1' AND classname = '语文') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F'))
结果显示:
该年该班该科不及格人数
1
4.求某个时间范围内某个科目及格的人数.
1.同上,先创建某个时间范围内的数据视图(在这不要再写了,因为前面已经创建了)
CREATE VIEW v_score2006 AS SELECT studentid, classname, classteacher, result,
testdate, banji
FROM scorenew
WHERE (testdate < '2007')
或者创建某个时间范围内某个特定班级的视图,这样会更加方便处理
如创建2006年语文科目的视图.
CREATE VIEW v_score2006china AS
SELECT studentid, classname, classteacher, result, testdate,banji FROM scorenew
WHERE (testdate < '2007') AND classname = '语文'
查找下看所建的视图是否正确
Select * from v_score2006china
2.求这个时间段参加该科目考试的人数
Select count (distinct studentid) as 该年该科目的考试人数 from v_score2006china
显示结果
该年该科目的考试人数
5
3.统计该年该科目不及格人数
SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006china t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006china
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate)) a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')
显示结果:
2002101
F
语文 2006-7-1
1
2002102
F
语文 2006-7-1
2
改成统计个数
SELECT COUNT(DISTINCT STUDENTID) AS 该年该科目不及格人数
FROM (SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006china t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006china
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate))
a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')) DERIVEDTBL
显示结果为
2
换成统计该年该班该科目不及格人数
SELECT STUDENTID, Result, CLASSNAME, TestDate, banji
FROM (SELECT STUDENTID, CLASSNAME, Result, TestDate, banji
FROM v_score2006china t
WHERE NOT EXISTS
(SELECT 1
FROM v_score2006china
WHERE STUDENTID = t .STUDENTID AND
CLASSNAME = t .CLASSNAME AND TestDate > t .TestDate) AND
banji = '1') a
GROUP BY STUDENTID, Result, CLASSNAME, TestDate, banji
HAVING (Result = 'F')
.本人不材,在此很多工作都是重复的工作.
最后再次感谢此次项目中对我很多帮助的朋友同事