假设我有一个表student
和一个exam
跟踪学生参加的所有考试的表,我如何找到所有通过或未参加任何类似于白名单的考试的学生?在此示例中,这意味着学生 1 和 2。
PS:pass
flagU
表示状态未知,active
flagN
表示考试已被删除,其余的标志是不言自明的。
说清楚一点,真正的用例其实是assessments
,我需要找出没有pending
评估的人可以参与,这样他们才能进行下一组程序。其他人则需要完成待处理的项目。
+-------------+------+
| student_idn | name |
+-------------+------+
| 1 | Mark |
| 2 | Jack |
| 3 | Jane |
| 4 | Jill |
+-------------+------+
+----------+-------------+------+--------+
| exam_idn | student_idn | pass | active |
+----------+-------------+------+--------+
| 1 | 1 | Y | Y |
| 2 | 1 | Y | Y |
| 3 | 1 | Y | Y |
| 4 | 2 | Y | Y |
| 5 | 2 | N | N |
| 6 | 3 | Y | Y |
| 7 | 3 | Y | Y |
| 8 | 3 | Y | Y |
| 9 | 3 | N | Y |
| 10 | 4 | U | Y |
+----------+-------------+------+--------+
我想出了下面的查询,但有没有更好的方法来做到这一点?我觉得这是 O(n) 或 O(nlogn) 取决于索引等不确定(任何人都知道最好的可能)因此应该接近最优?
SELECT
*
FROM student
WHERE NOT EXISTS (SELECT
*
FROM exam
WHERE exam.student_idn = student.student_idn
AND pass <> 'Y'
AND active = 'Y')
您描述的问题称为关系划分。基本上有两种方法可以接近它:
换句话说,将通过所有测试的学生转换为不存在该学生未通过的测试的学生。您在问题中的查询就是一个例子。
这种转换通常称为
De Morgan's laws for quantifiers
. 参见例如:https://philosophy.stackexchange.com/questions/28324/proving-de-morgans-laws-for-quantifiers
通过与考试相同数量的考试的学生。就像是:
我是用手机回答的,所以在回答时看不到问题,所以根据您的问题,我的回答的细节可能是错误的,但希望您能明白。
这个怎么样:
以下性能成本较低:
其实应该是这样的,这样就不需要把两张表连接起来了: