2

我正在为考试注册和评分构建软件:

我需要从这两个表中获取数据:

考试

|------------------------------------------------------------|           
| ExamId  |  ExamTitle  |  EducationId  |  ExamDate  |               
|------------------------------------------------------------|

考试尝试

|-----------------------------------------------------------------------------|
| ExamAttemptId  |  ExamId  |  StudentId  |  Grade  |  NotPresentCode  |        
|-----------------------------------------------------------------------------|
  1. 学生参加教育
  2. 教育有多重考试
  3. 学生每次考试最多有 6 次尝试
  4. 每次尝试都被评分或标记为不存在

如果满足以下条件,学生可以报名参加考试: - 尚未通过(2 级以下) - 未使用所有尝试

我想列出学生可以报名参加的所有考试。

它可能相当简单,但我无法理解它,现在我被卡住了!我已经尝试了一切,但还没有做对。这是我做过的最绝望的尝试之一(!):

CREATE PROCEDURE getExamsOpenForSignUp
@EducationId int,
@StudentId int
AS
SELECT ex.*
FROM Exams ex
LEFT JOIN (
    SELECT ExamId, COUNT(ExamId) AS NumAttempts
    FROM ExamAttempts
    WHERE StudentId = @StudentId AND grade < 2 OR grade IS NULL
    GROUP BY ExamId
) exGrouped ON ex.ExamId = exGrouped.ExamId
WHERE educationid = @EducationId and exGrouped.ExamId IS NULL OR exGrouped.NumAttempts < 6;
GO

我究竟做错了什么?请帮忙...

4

3 回答 3

1

您需要从所有可能的考试和学生的列表开始,然后淘汰那些不符合要求的。

select driver.StudentId, driver.ExamId
from (select @StudentId as StudentId, e.ExamId
      from exams e
      where e.EducationId = @EducationId
     ) driver left outer join
     (select ea.ExamId, ea.StudentId
      from ExamAttempts ea
      group by ea.ExamId, ea.StudentId
      having max(grade) >= 2 or -- passed
             count(*) >= 6
     ) NotEligible
     on driver.ExamId = NotEligible.ExamId and
        driver.StudentId = NotEligible.StudentId
where NotEligible.ExamId is NULL 

此查询的结构非常具体。该driver表包含所有可能的组合。在这种情况下,您只有一名学生,所有考试都在“教育”中。然后左连接根据您的两个要求确定哪些符合条件。决赛where是选择不符合条件的考试或符合条件的考试。

于 2013-05-26T13:30:35.670 回答
1

检查这是否适用于您的 SP:

Select EduExams.ExamId
from
    (select * from Exams 
     where Exams.EducationId = @EducationId) EduExams 
left outer join 
    (select * from ExamAttempts 
     where ExamAttempts.StudentId = @StudentId) StudentAttempts
on EduExams.ExamID = StudentAttempts.ExamId
group by EduExams.ExamId
having count(StudentAttempts.ExamAttemptId) < 6 
       and ((max(StudentAttempts.Grade) is null) or (max(StudentAttempts.Grade) < 2))
于 2013-05-26T23:07:20.457 回答
0

好的,谢谢你们的帮助-非常感谢!

基于@Gordon Linoffs 解决方案。这就是我最终的结果:

SELECT driver.ExamId, driver.ExamTitle
FROM (
    SELECT @StudentId AS StudentId, e.ExamId, e.ExamTitle
    FROM exams e
    WHERE e.EducationId = @EducationId
) driver 
    LEFT JOIN (
        SELECT ea.ExamId, ea.StudentId
        FROM ExamAttempts ea
        WHERE ea.studentId = @StudentId
        GROUP BY ea.ExamId, ea.StudentId
        HAVING MAX(grade) >= 2 OR COUNT(*) >= 6
    ) NotEligible
        ON driver.ExamId = NotEligible.ExamId AND driver.StudentId = NotEligible.StudentId
WHERE NotEligible.ExamId IS NULL
于 2013-05-30T09:40:11.217 回答