MySQL:跨行测试多个值

时间:2014-09-20 22:14:04

标签: mysql

我已经获得了一个大学毕业生的MySQL数据库和一个名为“受试者”的表格。包括:StudentID,SubjectName,Exams。

考试专栏是针对每门课程的考试。他们的名字有第一部分,第二部分,第一部分,第二部分等。学位课程的考试名称与其他课程不同,所以名称以'部分'开头。仅适用于学位,而A科可能适用于职业会计课程。

该表的简化版本如下所示:

StudentID   Subject     Exam
--------------------------------------
1234        Mathematics Part I
5678        Music       Sect A
9101        Geography   Part I
1234        Accountancy Sect A

请注意,有时人们会切换到学位课程,如上面的1234。我被要求写一个查询,找到所有没有参加任何学位相关考试的人。因此,他们不应该在结果中返回1234,因为他们已经完成了学位相关的考试(数学第一部分)以及非学位考试(会计学部分A)。

这个查询带我走了一些路,但是错过了像1234这样做过两种类型考试的人:

SELECT `StudentID` FROM `Subjects` WHERE `Exam` NOT IN ('Part I', 'Part II', etc)

我无法弄清楚如何优化查询。我试过这个,但它崩溃phpMyAdmin所以我猜它错了!

SELECT `StudentID` FROM `Subjects` 
WHERE `Exam` NOT IN ('Part I', 'Part II') 
AND `StudentID` NOT IN(SELECT `StudentID` FROM `Subjects` WHERE `Exam` LIKE 'Pt I%') 

1 个答案:

答案 0 :(得分:0)

  

这个查询带我走了一些路,但是错过了像1234这样做过两种类型考试的人:

     

SELECT StudentID FROM Subjects WHERE Exam NOT IN(' Part I',' Part II'等)

正如您所注意到的,此查询将多次返回多个考试的学生。它只会过滤掉你不想要的那些主题。学生1234选择Sect A的元组将保留。

要解决这个问题,你需要考虑另一种方式:你想要的学生那些不是你不想要的学生

首先,你得到所有想要的学生,一次:

SELECT DISTINCT `StudentID` 
    FROM `Subjects` 
    WHERE `Exam` IN ('Part I', 'Part II', etc)

现在,您要查询此列表中的学生列表。您可以通过LEFT JOIN所有科目列表(学生多次出席)和不需要的学生列表来完成此操作。只要完整列表中的名称可以与不需要的学生匹配,就会相应地填充不需要的。*列。如果无法完成此操作(即主题不属于不受欢迎的学生),则这些列将为NULL。

所以你只需选择那些unwanted.StudentId IS NULL的元组。这些将填充第一个表格的列。其中您只需要StudentID。由于StudentID可能会多次出现,因此您也会在外部DISTINCT上添加SELECT子句。

SELECT DISTINCT wanted.StudentID FROM `Subjects` AS wanted
    LEFT JOIN (
        SELECT DISTINCT `StudentID` 
             FROM `Subjects` 
             WHERE `Exam`  IN ('Part I', 'Part II', etc)
    ) AS unwanted
    ON (wanted.StudentId = unwanted.StudentId)
    WHERE unwanted.StudentId IS NULL;

Here你可以看到一个SQL小提琴;它按预期学生5678返回。