在關係數據庫中,最常用的操作就是查詢。
基本查詢
要查詢數據庫表的數據,我們使用如下的SQL語句:
SELECT * FROM <表名>
SELECT查詢的結果是一個二維表。
條件查詢
使用SELECT * FROM <表名>
可以查詢到一張表的所有記錄。但是很多時候並不希望獲得所有記錄,而是根據條件選擇性地獲取指定條件的記錄。
SELECT語句可以通過WHERE
條件來設定查詢條件,查詢結果是滿足查詢條件的記錄。
例如查詢學生表中成績大於90的學生記錄:
SELECT * FROM students WHERE score>=90;
使用AND
表示並列條件:
SELECT FROM * students WHERE score>=90 AND gender='F';
使用OR
表示邏輯或:
SELECT FROM * students WHERE score >=90 OR gender ='F';
組合條件使用小括號()
包裹:
SELECT FROM * students WHERE (score>=60 AND score<=90) OR gender='F';
使用LIKE
表示相似,其中%
符號表示任意字符:
SELECT FROM * WHERE name LIKE '小%';
條件運算優先級次序爲:NOT
> AND > OR
。
投影查詢
使用SELECT * FROM <表名> WHERE <條件>
可以選出表中的若干條記錄。我們注意到返回的二維表結構和原表是相同的,即結果集的所有列與原表的所有列都一一對應。
如果我們只希望返回某些列的數據,而不是所有列的數據,我們可以用SELECT 列1, 列2, 列3 FROM ...
,讓結果集僅包含指定列。這種操作稱爲投影查詢。
使用SELECT 列1, 列2, 列3 FROM ...
時,還可以給每一列起個別名,這樣,結果集的列名就可以與原表的列名不同。它的語法是SELECT 列1 別名1, 列2 別名2 FROM ...
。
SELECT id pk,name nickname FROM students WHERE score>90;
排序
我們使用SELECT
查詢時,查詢結果集通常是按照id
排序的,也就是根據主鍵排序。如果我們要根據其他條件排序怎麼辦?可以加上ORDER BY
子句。
SELECT id,name,gender score FROM studentd ORDER BY score;
如果要反過來,按照成績從高到底排序,我們可以加上DESC
表示“倒序”:
SELECT id,name,gender score FROM studentd ORDER BY score DESC;
如果score
列有相同的數據,要進一步排序,可以繼續添加列名。例如,使用ORDER BY score DESC, gender
表示先按score
列倒序,如果有相同分數的,再按gender
列排序:
SELECT id, name, gender, score FROM students ORDER BY score DESC, gender;
默認的排序規則是ASC
:“升序”,即從小到大。ASC
可以省略。
如果有WHERE
子句,那麼ORDER BY
子句要放到WHERE
子句後面。
SELECT id, name, gender, score FROM students WHERE class_id=1 ORDER BY score DESC;
分頁查詢
使用SELECT
查詢時,如果結果集數據量很大,放在一個頁面顯示的話數據量太大,不如分頁顯示。
這個查詢可以通過LIMIT <M> OFFSET <N>
子句實現:
SELECT id, name, gender, score FROM students ORDER BY score DESC
LIMIT 3 OFFSET 0;
上述查詢LIMIT 3 OFFSET 0
表示,對結果集從0號記錄開始,最多取3條。
如果要查詢第2頁,那麼我們只需要“跳過”頭3條記錄,也就是對結果集從3號記錄開始查詢,把OFFSET
設定爲3:
SELECT id, name, gender, score FROM students ORDER BY score DESC
LIMIT 3 OFFSET 3;
在MySQL
中,LIMIT 15 OFFSET 30
還可以簡寫成LIMIT 30, 15
。
使用LIMIT <M> OFFSET <N>
分頁時,隨着N
越來越大,查詢效率也會越來越低。
聚合查詢
如果我們要統計一張表的數據量,例如,想查詢students
表一共有多少條記錄,難道必須用SELECT * FROM students
查出來然後再數一數有多少行嗎?
這個方法當然可以,但是比較弱智。對於統計總數、平均數這類計算,SQL提供了專門的聚合函數,使用聚合函數進行查詢,就是聚合查詢,它可以快速獲得結果。
仍然以查詢students
表一共有多少條記錄爲例,我們可以使用SQL內置的COUNT()
函數查詢:
SELECT COUNT(*) boys FROM students WHERE gender='M';
除了COUNT()
函數外,SQL還提供瞭如下聚合函數:
函數 | 說明 |
---|---|
SUM | 計算某一列的合計值,該列必須爲數值類型 |
AVG | 計算某一列的平均值,該列必須爲數值類型 |
MAX | 計算某一列的最大值 |
MIN | 計算某一列的最小值 |
要特別注意:如果聚合查詢的WHERE
條件沒有匹配到任何行,COUNT()
會返回0,而SUM()
、AVG()
、MAX()
和MIN()
會返回NULL
分組
SQL提供了“分組聚合”的功能來實現對多個組別的聚合:
SELECT class_id,COUNT(*) num FROM students GROUP BY class_id;
也可以使用多個列進行分組。例如,我們想統計各班的男生和女生人數:
SELECT class_id, gender, COUNT(*) num FROM students GROUP BY class_id, gender;
跨表查詢
SELECT查詢不但可以從一張表查詢數據,還可以從多張表同時查詢數據。查詢多張表的語法是:SELECT * FROM <表1> <表2>
。
SELECT * FROM students, classes;
這種一次查詢兩個表的數據,查詢的結果也是一個二維表,它是students
表和classes
表的“乘積”,即students
表的每一行與classes
表的每一行都兩兩拼在一起返回。結果集的列數是students
表和classes
表的列數之和,行數是students
表和classes
表的行數之積。
這種多表查詢又稱笛卡爾查詢,使用笛卡爾查詢時要非常小心,由於結果集是目標表的行數乘積,對兩個各自有100行記錄的表進行笛卡爾查詢將返回1萬條記錄,對兩個各自有1萬行記錄的表進行笛卡爾查詢將返回1億條記錄。
上述查詢的結果集有兩列id
和兩列name
,兩列id
是因爲其中一列是students
表的id
,而另一列是classes
表的id
,但是在結果集中,不好區分。要解決這個問題,我們仍然可以利用投影查詢的“設置列的別名”來給兩個表各自的id
和name
列起別名:
SELECT
students.id sid,
students.name,
students.gender,
students.score,
classes.id cid,
classes.name cname
FROM students, classes;
用表名.列名
這種方式列舉兩個表的所有列實在是很麻煩,所以SQL還允許給表設置一個別名,讓我們在投影查詢中引用起來稍微簡潔一點:
SELECT
s.id sid,
s.name,
s.gender,
s.score,
c.id cid,
c.name cname
FROM students s, classes c;
連接查詢
連接查詢是另一種類型的多表查詢。連接查詢對多個表進行JOIN運算,簡單地說,就是先確定一個主表作爲結果集,然後,把其他表的行有選擇性地“連接”在主表結果集上。
最常用的一種是內連接INNER JOIN,其原理示意圖如下:
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
INNER JOIN classes c
ON s.class_id = c.id;
其次有外連接,包括:左連接、右連接和全連接
LEFT/RIGHT/FULL OUTER JOIN