If-Not-Exists

我如何辨識所有通過的學生?

  • October 29, 2016

假設我有一個表student和一個exam跟踪學生參加的所有考試的表,我如何找到所有通過或未參加任何類似於白名單的考試的學生?在此範例中,這意味著學生 1 和 2。

PS:passflagU表示狀態未知,activeflagN表示考試已被刪除,其餘的標誌是不言自明的。

說清楚一點,真正的案例其實是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')

您描述的問題稱為關係劃分。基本上有兩種方法可以接近它:

  1. 將所有 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

  1. 通過與考試相同數量的考試的學生。就像是:
SELECT student_id
FROM tests
WHERE passed = 'y' 
GROUP BY student_id
HAVING COUNT(1) = (SELECT COUNT(DISTINCT test_id) 
                   FROM tests)

我是用手機回答的,所以在回答時看不到問題,所以根據您的問題,我的回答的細節可能是錯誤的,但希望您能明白。

引用自:https://dba.stackexchange.com/questions/153528