1. 特點 1.1. 將多行數據作為整體來表達高級的條件 1.2. 使用關聯子查詢時性能仍然非常好 1.3. EXISTS的參數不像是單一值 1.3.1. 參數是行數據的集合 2. 什麼是謂詞 2.1. 一種特殊的函數,返回值是真值 2.2. 返回值都是true、false或者unknown 2.2 ...
1. 特點
1.1. 將多行數據作為整體來表達高級的條件
1.2. 使用關聯子查詢時性能仍然非常好
1.3. EXISTS的參數不像是單一值
1.3.1. 參數是行數據的集合
2. 什麼是謂詞
2.1. 一種特殊的函數,返回值是真值
2.2. 返回值都是true、false或者unknown
2.2.1. 一般的謂詞邏輯里沒有unknown
2.2.2. SQL採用的是三值邏輯,因此具有三種真值
2.3. 謂詞邏輯提供謂詞是為了判斷命題(可以理解成陳述句)的真假
2.3.1. 為命題分析提供了函數式的方法
2.4. 只有能讓WHERE子句的返回值為真的命題,才能從表(命題的集合)中查詢到
3. 謂詞的階
3.1. 階(order)是用來區分集合或謂詞的階數的概念
3.2. 一階謂詞
3.2.1. =或者BETWEEEN等輸入值為一行的謂詞
3.3. 二階謂詞
3.3.1. EXISTS這樣輸入值為行的集合的謂詞
3.3.2. 謂詞也是函數的一種,因此我們也可以說EXISTS是高階函數
3.4. 三階謂詞
3.4.1. 輸入值為“集合的集合”的謂詞
3.5. 四階謂詞
3.5.1. 輸入值為“集合的集合的集合”的謂詞
3.6. SQL里並不會出現三階以上的情況
4. SELECT子句的列表
4.1. 通配符:SELECT *
4.2. 常量:SELECT ‘這裡的內容任意’
4.3. 列名:SELECT col
5. 全稱量化和存在量化
5.1. 形式語言沒必要同時顯式地支持EXISTS和FORALL兩者
5.1.1. 因為全稱量詞和存在量詞只要定義了一個,另一個就可以被推導出來
5.1.2. ∀ xPx = ¬ ∃ x¬P
5.1.3. 所有的x都滿足條件P=不存在不滿足條件P的x
5.1.4. ∃ xPx = ¬ ∀ x¬Px
5.1.5. 存在x滿足條件P=並非所有的x都不滿足條件P
5.2. SQL支持EXISTS,不支持FORALL
5.2.1. SQL中沒有與全稱量詞相當的謂詞,可以使用NOT EXISTS代替
5.3. 全稱量詞
5.3.1. 所有的x都滿足條件P
5.4. 存在量詞
5.4.1. 存在(至少一個)滿足條件P的x
6. 查詢表中“不”存在的數據
6.1. 示例
6.1.1.
6.1.1.1.
SELECT DISTINCT M1.meeting, M2.person
FROM Meetings M1 CROSS JOIN Meetings M2;
6.1.1.2. 所有人都參加了全部會議時
6.1.1.3. --求出缺席者的SQL語句(1):存在量化的應用
SELECT DISTINCT M1.meeting, M2.person
FROM Meetings M1 CROSS JOIN Meetings M2
WHERE NOT EXISTS
(SELECT *
FROM Meetings M3
WHERE M1.meeting = M3.meeting
AND M2.person = M3.person);
6.1.1.3.1. ----求出缺席者的SQL語句(2):使用差集運算
SELECT M1.meeting, M2.person
FROM Meetings M1, Meetings M2
EXCEPT
SELECT meeting, person
FROM Meetings;
6.1.1.3.2. NOT EXISTS直接具備了差集運算的功能
7. “肯定⇔雙重否定”之間的轉換
7.1. 示例
7.1.1.
7.1.2. 所有科目分數都在50分以上
7.1.2.1. 沒有一個科目分數不滿50分
7.1.3.
SELECT DISTINCT student_id
FROM TestScores TS1
WHERE NOT EXISTS --不存在滿足以下條件的行
(SELECT *
FROM TestScores TS2
WHERE TS2.student_id = TS1.student_id
AND TS2.score < 50); --分數不滿50分的科目
7.1.4. 某個學生的所有行數據中,如果科目是數學,則分數在80分以上;如果科目是語文,則分數在50分以上。
7.1.4.1.
SELECT DISTINCT student_id
FROM TestScores TS1
WHERE subject IN (’數學’, ’語文’)
AND NOT EXISTS
(SELECT *
FROM TestScores TS2
WHERE TS2.student_id = TS1.student_id
AND 1 = CASE WHEN subject =’數學’AND score < 80 THEN 1
WHEN subject =’語文’AND score < 50 THEN 1
ELSE 0 END);
7.1.4.1.1.
SELECT student_id
FROM TestScores TS1
WHERE subject IN (’數學’, ’語文’)
AND NOT EXISTS
(SELECT *
FROM TestScores TS2
WHERE TS2.student_id = TS1.student_id
AND 1 = CASE WHEN subject =’數學’AND score < 80 THEN 1
WHEN subject =’語文’AND score < 50 THEN 1
ELSE 0 END)
GROUP BY student_id
HAVING COUNT(*) = 2; --必須兩門科目都有分數
7.1.4.1.2. EXISTS和HAVING有一個地方很像,即都是以集合而不是個體為單位來操作數據
8. 集合VS謂詞
8.1. 示例
8.1.1.
8.1.2. 查詢出哪些項目已經完成到了工程1
8.1.2.1. --查詢完成到了工程1的項目:面向集合的解法
SELECT project_id
FROM Projects
GROUP BY project_id
HAVING COUNT(*) = SUM(CASE WHEN step_nbr <= 1 AND status =’完成’THEN 1
WHEN step_nbr > 1 AND status =’等待’THEN 1
ELSE 0 END);
8.1.2.1.1. --查詢完成到了工程1的項目:謂詞邏輯的解法
SELECT *
FROM Projects P1
WHERE NOT EXISTS
(SELECT status
FROM Projects P2
WHERE P1.project_id = P2. project_id --以項目為單位進行條件判斷
AND status <> CASE WHEN step_nbr <= 1 --使用雙重否定來表達全稱量化命題
THEN ’完成’
ELSE ’等待’ END);
8.1.2.1.1.1. 性能好。只要有一行滿足條件,查詢就會終止
8.1.2.1.1.2. 結果里能包含的信息量更大
9. 對列進行量化
9.1. 示例::查詢全是1的行
9.1.1. --“列方向”的全稱量化:不優雅的解答
SELECT *
FROM ArrayTbl
WHERE col1 = 1
AND col2 = 1
·
·
·
AND col10 = 1;
9.1.1.1. --“列方向”的全稱量化:優雅的解答
SELECT *
FROM ArrayTbl
WHERE 1 = ALL (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
9.2. 示例:至少有一個9
9.2.1. --列方向的存在量化(1)
SELECT *
FROM ArrayTbl
WHERE 9 = ANY (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
9.2.1.1. --列方向的存在量化(2)
SELECT *
FROM ArrayTbl
WHERE 9 IN (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
9.2.1.1.1. 這種寫法也是被允許的
9.2.1.1.2. 如果左邊不是具體值而是NULL,這種寫法就不行了
9.2.2. --查詢全是NULL的行:錯誤的解法
SELECT *
FROM ArrayTbl
WHERE NULL = ALL (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
9.2.2.1. --查詢全是NULL的行:正確的解法
SELECT *
FROM ArrayTbl
WHERE COALESCE(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10) IS NULL;