寫在前面:本篇博客大部分內容參考數據庫系統概念(本科教學版)第三章(第三章部分的多表操作沒有在此處講,準備挪到第四章再一起討論)
下面的例子中的測試都是在MySQL數據庫中測試的
集合運算
此處集合運算的概念與數學中集合的概念類似,可以借助文氏圖加深理解。故此處對并運算進行展開,其他啊兩個自己類比,后面還會對集合運算的幾個注意點進提醒。
-
union(集合并運算)
- union 默認去除重復,并升序排序(因為涉及到排序,故而會有效率上的劣勢)
- union all 就可保留重復項,并且保留原序(不進行排序)
- 舉個栗子(現有兩張表如下)
-
stu_name age score Sunny 18 98 Robbin 18 96 James 19 67 Jane 17 82 -
tech_name age James 32 Marry 33 Lory 33 - 執行以下運算
得到如下結果(得到的結果沒有重復元素,但是沒有排序,說明MySQL數據庫在此處沒有對其進行排序輸出,但是Oracle數據庫是會對數據進行升序排序的)SELECT age FROM Student UNION SELECT age FROM Teacher
-
age 18 19 17 32 33 - 執行以下運算
得到如下結果(可以知道,UNION ALL 保留了重復元素)SELECT age FROM Student UNION ALL SELECT age FROM Teacher
-
age 18 18 19 17 32 33 33
-
-
intersect(集合交運算)
-
except(集合差運算)
-
Note:
- 參與集合運算的兩個視圖的列數要一致
- 舉個栗子
-- 下面的語句執行就會出錯 -- 因為第一個視圖有兩個字段,而第二個視圖只有一個字段,無法進行集合運算 SELECT age, score FROM Student UNION ALL SELECT age FROM Teacher
- 舉個栗子
- 參與集合運算的兩個視圖對應位置的字段的數據類型應該是一致的(數據類型兼容即可,字段名無需一致)
- 舉個栗子
上面的書法在Oracle數據庫里得到了證實,確實執行是會報錯的,-- 按上面的說法下面語句執行是非法的 -- 因為第二個字段的數據類型不兼容,一個是浮點型,一個是字符串類型 SELECT age, score FROM Student UNION ALL SELECT age, tech_name FROM Teacher
那MySQL數據庫呢?我們執行以下,得到以下結果 -
age score 18 98 18 19 67 17 82 32 James 33 Marry 33 Lory
- 舉個栗子
- 若無字段可加,又需保證列數相同,可控NULL做填充
- 舉個栗子
得到如下結果哦SELECT age, score FROM Student UNION ALL SELECT age, NULL FROM Teacher
-
age score 18 98 18 19 67 17 82 32 33 33
- 舉個栗子
- 集合運算的結果視圖的字段名以第一個結果集的字段名為主
- 舉個栗子
得到如下結果:SELECT stu_name FROM Student UNION SELECT tech_name FROM Teacher
-
stu_name Sunny Robbin Marry Lory Jane James
- 舉個栗子
- Oracle數據庫中,差運算不是except, 而是minus;Oracle數據庫union可以后面跟all, 但是interscet和minus后面不可以(不同數據庫不同)
- 參與集合運算的兩個視圖的列數要一致
空值NULL
- NULL就是不確定的值,參與數值運算和字符串運算時,不同的數據庫采取的處理不同;
- Oracle 數據庫中,NULL無論參與數值運算還是字符串運算,都會使整體為NULL
- 獲取系統時間
- Oracle數據庫的查詢語句必須有from
- 故采用如下方法獲取系統時間
-- 其中dual是Oracle數據庫系統自帶的一行一列的表 -- 其他數據庫沒有這個表 SELECT SYSDATE FROM dual
- MySQL就沒有這個限制
-- 在MySQL和SQL Server中用下面的語句就可獲得系統時間 SELECT SYSDATE
- 日期類型的運算
- 可與數值類型做加減運算(在Oracle數據庫里面單位為天,·.·在MySQL里面竟然是秒)
- 舉個栗子(MySQL里面測試)
得到如下結果SELECT SYSDATE() - 1, SYSDATE(), SYSDATE() + 1
-
'SYSDATE() - 1' 'SYSDATE()' 'SYSDATE() + 1' 20170919183000 2017-09-19 18:30:01 20170919183002
- 舉個栗子(MySQL里面測試)
- 可與日期類型做減運算,得到連個日期之前的差值
- 不可與日期類型做加運算(在Oracle數據庫執行日期間加運算直接報錯,Mysql數據庫直接真的返回兩個日期加以后的值,不過巨耗時,mmp)
- 與NULL值運算得NULL值(在Oracle和MySQL上測試結果都正確)
- 可與數值類型做加減運算(在Oracle數據庫里面單位為天,·.·在MySQL里面竟然是秒)
- where 子句,判斷是否為空
- 用is NULL 和 is not NULL 判斷
- 而不用 = NULL 和 != NULL
- 布爾變量有三個取值:TRUE,FALSE, NULL
- 三種取值以and,or相連時的結果,與并聯串聯電路的判斷類
- TRUE and NULL = NULL
- TRUE OR NULL = TRUE
- FALSE and NULL = FALSE
- FALSE OR NULL = NULL
- 舉個栗子
-- 下面的語句將會返回Student表中的所有信息 -- 因為where子句后面的條件為真 SELECT * FROM Student WHERE TRUE OR NULL
去重關鍵字 distinct
- 跟在SELECT的后面,并且置于所有字段的前面
- 會將其后的字段都作為判斷重復的條件
- 舉個栗子
-- 下面的語句就是列出學生表中的數據,并去除stu_name和age都相同的數據重復 SELECT DISTINCT stu_name, age FROM Student
聚集函數(Aggregate Functions)
多行輸入,一行輸出
- 此類函數有MIN,MAX,COUNT,AVG,SUM。其中AVG和SUM只能參與數值運算
-
聚集函數在使用時會忽略空值NULL
- 除了COUNT(*),COUNT(*)在統計的時候是不忽略空值的
-
Count
- 在計數時,忽略空值項
- 默認是統計重復項的,其中ALL是默認的,顧可以不顯示指明
COUNT(ALL age)
- 如果統計去除重復以后的結果,可如下面寫法
COUNT(DISTINCT age)
- Oracle中用作對null值數據處理的函數nvl
# 下面的語句表示對數據表中的分數做加和,如果遇到為空的項,則取其值為0 SELECT SUM(NVL(score, 0)) FROM Student
- COUNT(*)==>可返回滿足where子句條件的所有數據的數量
- 這是COUNT獨有的用法,其他聚集函數里面只能放字段或表達式
-
SUM
- SUM(age) + SUM(score) >= SUM(age + score)
- 因為聚集函數在使用時會忽略空值,而NULL值直接參與運算可能會導致整體為空,顧有上述結論
- 當且僅當數據中沒有空值時,上述等號成立
分組聚集(Aggregation)
- GROUP BY 字段序列
- GROUP BY 后面跟的字段序列作為分組條件,值相同的為一組
- 可以是多個字段(順序不影響結果)
-
當SELECT列表中出現了聚集函數,select中能出現以下字段
- 可以放group by 后面的字段
- 可以放聚集函數處理了的字段或表達式
上面兩種情況下的字段在每組的取值都是唯一的,故而可以保證結果集中每一項的行數是一致的
having, 解決where子句中不能包含聚集函數的問題