If-Not-Exists
我如何辨識所有通過的學生?
假設我有一個表
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')
您描述的問題稱為關係劃分。基本上有兩種方法可以接近它:
- 將所有 x : p(x) 轉換為不存在 x : not p(x)
換句話說,將通過所有測試的學生轉換為不存在該學生未通過的測試的學生。您在問題中的查詢就是一個例子。
這種轉換通常稱為
De Morgan's laws for quantifiers
. 參見例如:https://philosophy.stackexchange.com/questions/28324/proving-de-morgans-laws-for-quantifiers
- 通過與考試相同數量的考試的學生。就像是:
SELECT student_id FROM tests WHERE passed = 'y' GROUP BY student_id HAVING COUNT(1) = (SELECT COUNT(DISTINCT test_id) FROM tests)
我是用手機回答的,所以在回答時看不到問題,所以根據您的問題,我的回答的細節可能是錯誤的,但希望您能明白。