我有以下数据:
ExamEntry Student_ID Grade
11 1 80
12 2 70
13 3 20
14 3 68
15 4 75
我想找到所有通过考试的学生。在这种情况下,如果考试很少 那个学生参加了,我需要找到最后的结果。
所以,在这种情况下,我会让所有学生都过去了。
我可以通过一个快速查询找到它吗?我是这样做的:
查找条目列表 通过Student_ID
查找结果:
从()中的ExamEntry数据中选择ExamEntry。
但这非常慢 - 我得到大约1000个条目,这个2步过程需要10秒。
有更好的方法吗?
感谢。
答案 0 :(得分:6)
如果你的查询在你的表中有1000条记录很慢,那就有问题了。 对于现代数据库系统,包含1000个条目的表被认为非常小 最有可能的是,你没有为你的桌子提供(主要)钥匙?
如果学生至少在成绩高于所需的最低要求时通过,则适当的查询将是:
SELECT
Student_ID
, MAX(Grade) AS maxGrade
FROM table_name
GROUP BY Student_ID
HAVING maxGrade > MINIMUM_GRADE_NEEDED
如果您确实需要最新成绩高于最低成绩:
SELECT
Student_ID
, Grade
FROM table_name
WHERE ExamEntry IN (
SELECT
MAX(ExamEntry)
FROM table_name
GROUP BY Student_ID
)
HAVING Grade > MINIMUM_GRADE_NEEDED
答案 1 :(得分:1)
SELECT student_id, MAX(ExamEntry)
FROM data
WHERE Grade > :threshold
GROUP BY student_id
喜欢这个吗?
答案 2 :(得分:1)
我会假设你有一个学生表和测试表,你向我们展示的表是test_result表...(如果你没有类似的结构,你应该重新访问你的模式)< / p>
select s.id, s.name, t.name, max(r.score)
from student s
left outer join test_result r on r.student_id = s.id
left outer join test t on r.test_id = t.id
group by s.id, s.name, t.name
其中包含id的所有字段都应编入索引。
如果您的域中只有一个测试(类型)...那么查询将是
select s.id, s.name, max(r.score)
from student s
left outer join test_result r on r.student_id = s.id
group by s.id, s.name
答案 3 :(得分:1)
如前所述,索引是加速查询的强大工具。但是,索引的顺序非常重要。
按照(ExamEntry)然后(Student_ID)然后(等级)的顺序的索引将无法用于查找学生通过的考试。
如果您想要的是找到已通过的考试,那么相反顺序的索引将完全适合。这将使查询引擎能够快速识别已传递的检查行,并只处理这些行。
在MS SQL Server中,可以使用...
完成CREATE INDEX [IX_results] ON [dbo].[results]
(
[Grade],
[Student_ID],
[ExamEntry]
)
ON [PRIMARY]
(我建议阅读更多关于索引的信息,看看有哪些其他选项,比如ClusterdIndexes等等)
使用该索引,以下查询可以非常快速地忽略“失败”考试,并只显示通过考试的学生...
(这假设如果你的年龄超过60岁,即使你再次参加考试并获得27分,你也算作通行证。)
SELECT
Student_ID
FROM
[results]
WHERE
Grade >= 60
GROUP BY
Student_ID
如果您确定需要最新值,那么您需要将索引的顺序更改为类似...
CREATE INDEX [IX_results] ON [dbo].[results]
(
[Student_ID],
[ExamEntry],
[Grade]
)
ON [PRIMARY]
这是因为我们感兴趣的第一件事是任何特定学生的最新ExamEntry。使用以下查询可以实现哪些...
SELECT
*
FROM
[results]
WHERE
[results].ExamEntry = (
SELECT
MAX([student_results].ExamEntry)
FROM
[results] AS [student_results]
WHERE
[student_results].Student_ID = [results].student_id
)
AND [results].Grade > 60
像这样的子查询可能看起来很慢,特别是因为它似乎是对[结果]中的每一行执行的。
但事实并非如此......
- 主查询和子查询都引用相同的表
- 查询引擎扫描索引中的每个唯一Student_ID
- 为该Student_ID执行子查询
- 查询引擎已经在索引的那一部分中
- 因此不需要新的索引查找
编辑:
有人评论说,在1000条记录中,索引不相关。应该注意的是,该问题表明返回了1000条记录,而不是该表包含1000条记录。对于基本查询,只要说明,我打赌表中有超过1000条记录。也许这可以澄清一下?
编辑:
我刚调查了3个查询,每个查询999条记录(333名学生各3名考试成绩)
方法1:WHERE a.ExamEntry =(SELECT MAX(b.ExamEntry)FROM results [a] WHERE a.Student_ID = b.student_id)
方法2:WHERE a.ExamEntry IN(SELECT MAX(ExamEntry)FROM结果GROUP BY Student_ID)
方法3:使用INNER JOIN而不是IN子句
发现以下时间:
Method QueryCost(No Index) QueryCost(WithIndex)
1 23% 9%
2 38% 46%
3 38% 46%
因此,无论索引如何,查询1都会更快,但索引也肯定会使方法1更快。
原因是索引允许查找,否则您需要扫描。线性定律与平方定律之间的区别。
答案 4 :(得分:1)
我已经使用了这里给出的提示,这里我发现的查询运行速度比第一个快了近3个订单(.03秒而不是10秒):
SELECT ExamEntry, Student_ID, Grade from data,
( SELECT max(ExamEntry) as ExId GROUP BY Student_ID) as newdata
WHERE `data`.`ExamEntry`=`newdata`.`ExId` AND Grade > 60;
全部谢谢!
答案 5 :(得分:0)
感谢您的回答!!
我认为Dems可能最接近我的需要,但我会详细说明这个问题。
特定考试的查询也会返回~1K条目,当~1K是学生人数(由结果中的SELECT DISTINCT STUDENT_ID收到;),然后几乎全部通过,有些已经失败。
我在我的代码中执行以下查询: SELECT ExamEntry,考试中的Student_ID WHERE ExamEntry in(SELECT MAX(ExamEntry)from examams GROUP BY Student_ID)。当子查询返回大约1K个条目时,主查询似乎在循环中扫描它们,使得所有查询运行很长时间并且服务器负载为50%(Windows上为100%)。
我感觉有更好的方法:-),但还是找不到它。
答案 6 :(得分:0)
select examentry,student_id,grade
from data
where examentry in
(select max(examentry)
from data
where grade > 60
group by student_id)
答案 7 :(得分:0)
不要使用
where grade > 60
但
where grade between 60 and 100
应该更快