文章目錄
前言:
現在我們來看看SQL語法的用法,包括查詢語句的類型、語法格式和對應的使用場景
這篇我們講數據查詢
數據查詢語言是數據庫最基本的應用,其語法較爲複雜,包括簡單查詢、帶條件查詢、連接查詢、子查詢、集合運算、數據分組、排序和限制等
1. 簡單查詢
日常查詢中 最常用的就是用過FROM子句實現的查詢
語法:
SELECT [ , ... ] FROM table_reference [ , ... ]
使用方法:
SELECT項用於指定要查詢的列,FROM指定要從哪個表中查詢。
如果要查詢所有列,可以在SELECT後面使用*號,如果只查詢特定的列,可以直接在SELECT後面指定列名,列名之間用逗號(,)隔開。
例子1:
查詢training表中的所有列
SELECT * FROM training;
2. 關鍵字 DISTINCT
從SELECT的結果集中刪除所有重複的行,使結果集中的每行都是唯一的。去重複值查詢
例子:
利用distinct關鍵字來查詢員工的崗位和獎金,去除崗位和獎金相同的記錄。
select distinct job, bonus from sections;
3. 查詢列的選擇
例子1:
從多個表中查找多個列
其中,列a、b是表t1中的列,f1、f2是表t2中的列
SELECT a, b, f1, f2 FROM t1, t2;
例子2:
查兩個字段計算出來的
SELECT a+b FROM t1;
例子3:
如果某兩個或某幾個表正好有一些共同的列名,推薦使用表名限定列名。不限定列名可以得到查詢結果,但使用完全限定的表和列名稱,可以減少數據庫內部的處理工作量,從而提升查詢的返回性能
SELECT t1.f1, t2.f1 from t1, t2;
4. 別名
通過使用子句AS some_name,可以爲表名稱或列名稱指定另一個標題名顯示,一般創建別名是爲了讓列名稱的可讀性更強
-
語法格式:
列和表的SQL別名分別跟在相應的列名和表名後面,中間可以加或不加一個“AS”關鍵字。也可以用雙引號的方式來表示別名。例子:
表名限定列名,查詢學號sid爲10的學生的數學成績和英語成績
select a.sid,a.score as math, b.score as english from math a,english b where a.sid = 10 and b.sid = 10;
5. 條件查詢
在SELECT語句中,可以通過設置條件以達到更精確的查詢。條件由表達式與操作符共同指定,且條件返回的值是TRUE,FALSE或UNKNOWN。查詢條件可以應用於WHERE子句,HAVING子句。
-
比較操作符
“>, <,>=,<=, !=, <>,=”指定的比較查詢條件。當查詢條件中和數字比較,可以使用單引號引起,也可以不用,當和字符及日期類型的數據比較,則必須用單引號引起 -
邏輯操作符
常用的邏輯操作符有AND、OR和NOT,他們的運算結果有三個值,分別爲TRUE、FALSE和NULL,其中NULL代表未知。他們運算優先級順序爲:NOT>AND>OR運算規則表
a | b | a AND b | a OR b | NOT a |
---|---|---|---|---|
TRUE | TRUE | TRUE | TRUE | FALSE |
TRUE | FALSE | FALSE | TRUE | FALSE |
TRUE | NULL | NULL | TRUE | FALSE |
FALSE | FALSE | FALSE | FALSE | TRUE |
FALSE | NULL | FALSE | NULL | TRUE |
NULL | NULL | NULL | NULL | NULL |
- 測試運算符
測試運算符指定的範圍查詢條件
運算符 | 描述 |
---|---|
IN/NOT IN | 元素在/不在指定的集合中。 |
EXISTS/NOT EXISTS | 存在/不存在符合條件的元素。 |
ANY/SOME | 存在一個值滿足條件。SOME是ANY的同義詞。 |
ALL | 全部值滿足條件。 |
BETWEEN…AND… | 在兩者之間,例如a BETWEEN x AND y等效於a>= x and a <= y。 |
IS NULL/IS NOT NULL | 等於/不等於NULL。 |
LIKE/NOT LIKE | 字符串模式匹配/不匹配。 |
REGEXP | 字符串與正則表達式相匹配,僅支持STRING類型。 |
REGEXP_LIKE | 字符串與正則表達式相匹配,支持STRING類型和NUMBER類型。 |
例子1:
從表bonuses_depa中查詢崗位爲developer,且獎金>8000的職員信息
select * from bonuses_depa where job = 'developer' and bonus > 8000;
例子2:
從表bonuses_depa中查詢姓wang,且獎金在8500~9500之間的職員信息
select * from bonuses_depa where name like 'wang%' and bonus between 8500 and 9500;
補充:
通配符 %:表示任意數量的字符,包括無字符,用於like和not like語句中。
_:下劃線,表示確切的一個未知字符,用於like和not like語句中。
6. join連接查詢
實際應用中所需要的數據,經常會需要查詢兩個或兩個以上的表。這種查詢兩個或兩個以上數據表或視圖的查詢叫做連接查詢。連接查詢通常建立在存在相互關係的父子表之間。(只要在FROM子句中出現多個表時,數據庫就會執行連接)
大多數連接查詢包含至少一個連接條件,連接條件可以在FROM子句中也可以在WHERE子句中
舉個例子: 對A(4條記錄)和B(5條記錄)兩個表做不指定條件的連接查詢時,會得到20(4×5)條記錄
語法格式:
SELECT [ , ... ] FROM table_reference
[LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER] | INNER]
JOIN table_reference
[ON { predicate } [ { AND | OR } condition ] [ , ... n ]]
注:table_reference 子句中可以是普通表、視圖、子查詢
-
內連接
內連接的關鍵字爲inner join,其中inner可以省略。使用內連接,連接執行順序必然遵循語句中所寫的表的順序。例子:
查詢員工ID、最高學歷和考試分數。使用training和education兩個相關的列(staff_id)做查詢操作
SELECT e.staff_id, e.higest_degree, t.score FROM education e JOIN training t ON (e.staff_id = t.staff_id);
- 外連接
- 內連接所指定的兩個數據源處於平等的地位。而外連接不同,外連接以一個數據源爲基礎,將另外一個數據源與之進行條件匹配。
- 內連接返回兩個表中所有滿足連接條件的數據記錄。外連接不僅返回滿足連接條件的記錄,還將返回不滿足連接條件的記錄。
- 外連接又分爲左外連接、右外連接和全外連接。
-
左外連接
又稱左連接,如圖所示,是指以左邊的表爲基礎表進行查詢。
根據指定連接條件關聯右表,獲取基礎表以及和條件匹配的右表數據,未匹配條件的右表對應的字段位置填上NULL。例子:
SELECT e.staff_id, e.higest_degree, t.score FROM education e LEFT JOIN training t ON (e.staff_id = t.staff_id);
-
右外連接
又稱右連接,是指以右邊的表爲基礎表,在內連接的基礎上也查詢右邊表中有記錄,而左邊的表中沒有記錄的數據(左邊用NULL值填充)。例子:
SELECT e.staff_id, e.higest_degree, t.score FROM education e RIGHT JOIN training t ON (e.staff_id = t.staff_id);
-
全外連接
又稱全連接,是指除了返回兩個表中滿足連接條件的記錄,還會返回兩個表中不滿足連接條件的所有其它行(不匹配的另外一邊用NULL值填充)例子:
SELECT e.staff_id, e.higest_degree, t.score FROM education e FULL JOIN training t ON (e.staff_id = t.staff_id);
-
半連接
半連接(Semi Join)是一種特殊的連接類型,在SQL中沒有指定的關鍵字,通過在WHERE後面使用IN或EXISTS子查詢實現。當IN/EXISTS右側的多行滿足子查詢的條件時,主查詢也只返回一行與IN/EXISTS子查詢匹配的行,而不是複製左側的行。例子:
查看參加培訓的員工的教育信息。即使training表中的許多行可能與子查詢匹配(即同一個staff_id下有多個職員),也只需要從表training返回一行。
SELECT staff_id, higest_degree, education_note FROM education WHERE EXISTS (SELECT * FROM training WHERE education.staff_id = training.staff_id);
-
反連接
反連接(Anti Join)是一種特殊的連接類型,在SQL中沒有指定的關鍵字,通過在WHERE後面使用NOT IN或NOT EXISTS子查詢實現。返回所有不滿足條件的行。這個關係的概念跟半連接相反。例子:
SELECT staff_id, higest_degree, education_note FROM education WHERE staff_id NOT IN (SELECT staff_id FROM training);
7. 子查詢
查詢是指在查詢、建表或插入語句的內部嵌入查詢,以獲得臨時結果集。
子查詢可以分爲相關子查詢和非相關子查詢
子查詢類型 | 描述 |
---|---|
相關子查詢 | 執行查詢的時候先取得外層查詢的一個屬性值,然後執行與此屬性值相關的子查詢,執行完畢後再取得外層查詢的下一個值,依次再來重複執行子查詢。 |
非相關子查詢 | 子查詢獨立於外層語句(主查詢),子查詢的執行不需要提前取得父查詢的值,只是作爲父查詢的查詢條件。查詢執行時子查詢和主查詢可分爲兩個獨立的步驟,即先執行子查詢,再執行主查詢。 |
子查詢可以出現在FROM子句、WHERE子句、以及WITH AS子句中。
例子1:
通過相關子查詢,查找每個部門中高出部門平均工資的人員
SELECT s1.last_name, s1.section_id, s1.salary
FROM staffs s1
WHERE salary >(SELECT avg(salary) FROM staffs s2 WHERE s2.section_id = s1.section_id)
ORDER BY s1.section_id;
對於staffs表的每一行,父查詢使用相關子查詢來計算同一部門成員的平均工資。相關子查詢爲staffs表的每一行執行以下步驟:
確定行的section_id。
然後使用section_id來評估父查詢。
如果此行中工資大於所在部門的平均工資,則返回該行。
對於staffs表的每一行,子查詢都將被計算一次。
例子2:
WITH子查詢:查詢培訓過big data課程的員工信息
WITH bigdata_staffs AS (select staff_id,exam_date from training where course_name = 'BIG DATA' )select * from bigdata_staffs;
例子3:
通過子查詢建立一個和表training具有相同表結構的表
CREATE TABLE training_new AS SELECT * FROM training WHERE 1<>1;
注:<>是不等於的意思,1<>1的條件不成立,所以子查詢不會返回數據
例子4:
通過子查詢向表training_new表中插入training表的所有數據
INSERT training_new SELECT * FROM training;
8. 合併結果集
除子查詢外,還可以使用集合運算符處理多個查詢的結果集,輸出最終結果
使用語法:
select_statement UNION [ALL] select_subquery
注:Union運算符:將多個查詢塊的結果集合併爲一個結果集輸出
使用方法:
• 每個查詢塊的查詢列數目必須相同。
• 每個查詢塊對應的查詢列必須爲相同數據類型或同一數據類型組。
•關鍵字ALL的意思是保持所有重複數據,而沒有ALL的情況下表示刪除所有重複數據。
理解:
例子:
現有兩個部門的員工信息,查詢獲得獎金超過7000的員工信息
SELECT staff_id, name, bonus FROM bonuses_depa1 WHERE bonus > 7000 UNION ALL SELECT
staff_id, name, bonus FROM bonuses_depa2 WHERE bonus > 7000 ;
9. 差異結果集
使用MINUS/ EXCEPT運算符。對查詢結果集的減法,計算存在於左邊查詢語句的輸出、而不存在於右邊查詢語句輸出的結果
比如:A minus B C就意味着將結果集A去除結果集B和結果集C中所包含的所有記錄後的結果,即在A中存在,而在B、 C中不存在的記錄
語法格式:
select_statement MINUS/EXCEPT select_statement2 [ ... ]
理解:
10. 數據分組
-
GROUP BY
數據庫查詢中,分組是一個非常重要的應用。分組是指將數據表中的記錄以某個或者某些列爲標準,值相等的劃分爲一組。語法格式
GROUP BY { column_name } [ , ... ]
使用方法:
○ GROUP BY子句中的表達式可以包含FROM子句中表,視圖的任何列,無論這些列是否出現在SELECT列表中。
○ GROUP BY子句對行進行分組,但不保證結果集的順序。 要對分組進行排序,請使用ORDER BY子句。
○ GROUPBY後的表達式可以使用括號,如: group by (expr1, expr2),或者 group by(expr1), (expr2)。但不支持 group by (expr1, expr2), expr3 格式。
例子:
該部門按照崗位和獎金分組,查詢每組員工數,結果按人數升序排序
select job, bonus, count(staff_id) sum from bonuses_depa group by(job,bonus) order by sum;
2. HAVING子句
與GROUP BY子句配合用來選擇特殊的組。HAVING子句將組的一些屬性與一個常數值比較,只有滿足HAVING子句中條件的組纔會被提取出來
語法格式:
HAVING condition [ , ... ]
例子:
查詢表sections中崗位人數大於3的各崗位員工總數。
select job, count(staff_id) from bonuses_depa group by job having count(staff_id) >3;
11. 數據排序
-
ORDER BY子句
使用ORDER BY子句對查詢語句返回的行根據指定的列進行排序。如果沒有ORDER BY子句,則多次執行的同一查詢將不一定以相同的順序進行行的檢索。
語法格式:
ORDER BY { column_name | number | expression } [ ASC | DESC ][ NULLS FIRST | NULLS LAST ] [ , ... ]
使用方式:
○ column_name | number | expression 表示 order by 後面可以跟列名、數字、表達式(跟數字:order by 1 表示 根據查詢選擇列中第一個字段排序。跟表達式:order by(column1+column2) 表示根據column1與column2的和的大小來排序。)
○ ORDER BY語句默認按照升序對記錄進行排序。如果希望按照降序對記錄進行排序,請使用DESC關鍵字。
○ NULLS FIRST | NULLS LAST 關鍵字指定ORDER BY列中NULL值的排序位置,FIRST表示將NULL值排在最前面,LAST表示將NULL值排在最後面,若不指定該選項, ASC默認爲NULLS LAST, DESC默認爲NULLS FIRST。
例子:
查詢下表bonuses_depa中各工種的獎金信息,查詢結果先按bonus升序排列,然後按name降序排列
select * from bonuses_depa order by bonus,name desc;
12. 數據限制
數據限制功能包括兩個獨立的子句,LIMIT子句和OFFSET子句
- LIMIT子句允許限制查詢返回的行。 可以指定偏移量,以及要返回的行數或行百分比。 可以使用此子句實現top-N報表。要獲得一致的結果,請指定ORDER BY子句以確保確定性排序順序
LIMIT { count | ALL }
- OFFSET子句設置開始返回的位置
OFFSET start
使用方法
○ start:指定在返回行之前要跳過的行數。
○ count:指定要返回的最大行數。
○ start和count都被指定時,在開始計算要返回的count行之前會跳過start行
○ LIMIT 5,20與LIMIT 20 OFFSET 5及OFFSET 5 LIMIT 20 均表示跳過5行後輸出20行記錄
例子:
查詢下表 bonuses_depa中的員工信息。通過增加LIMIT 2 OFFSET 1限定查詢時跳過前1行後,查詢總共2行數據
SELECT name, job, bonus FROM bonuses_depa LIMIT 2 OFFSET 1;