一、前言
select語句可以說是mysql中最常用的語句了,除了select還有insert、delete、update等關鍵詞,這些關鍵詞是mysql的保留詞,我們在定義表名,欄位名,變量名的時候不要使用這些保留詞。
select的作用就是從一張表或者多張表中查詢我們想要的數據。這一章我們會講select的基礎知識。
二、創建一張王者榮耀表
首先我們創建一個王者榮耀的數據表,這張表有69的英雄,23個屬性值。這裡我們用陳暘老師的SQL文件(github地址:github.com/cystanford/sql_heros_data),大家可以下載下來用,具體的表如下:
數據表中這 24 個欄位(除了 id 以外),分別代表的含義見下圖:
三、查詢列
如果我們要對數據表中某一列的數據進行檢索,可以在select後面加上列名即可。比如:
select name from heros;(查詢一列)
運行結果如下:
select name, hp_max, mp_max, attack_max, defense_max from heros;(查詢多列)
如果你記不住欄位名字或者想查詢所有的數據可以使用:select *:
select * from heros;
結果如下:
我們在做數據探索的時候,select *還是很有用的,這樣我們就不需要寫很長的 select 語句了。但是在生產環境時要儘量避免使用select*
四、起別名
在select查詢的時候,如果欄位名太麻煩不好記,我們可以給列名起別名,比如:最大法力值hp_max 為了方便記憶我們可以寫成hm。
select name as n, hp_max as hm, mp_max as mm, attack_max as am, defense_max as dm from heros;
運行結果和上面多列檢索的運行結果是一樣的,只是將列名改成了 n、hm、mm、am 和 dm。
五、查詢常數
SELECT 查詢還可以對常數進行查詢。對的,就是在 SELECT 查詢結果中增加一列固定的常數列,這列的取值是我們指定的,而不是從數據表中動態取出的。
你可能會問為什麼我們還要對常數進行查詢呢?SQL 中的 SELECT 語法的確提供了這個功能,一般來說我們只從一個表中查詢數據,通常不需要增加一個固定的常數列,但如果我們想整合不同的數據源,用常數列作為這個表的標記,就需要查詢常數。
比如說,我們想對 heros 數據表中的英雄名進行查詢,同時增加一列欄位platform,這個欄位固定值為「王者榮耀」,可以這樣寫:
SQL:SELECT '王者榮耀' as platform, name FROM heros;
運行結果如下:
在這個 SQL 語句中,我們虛構了一個platform欄位,並且把它設置為固定值「王者榮耀」。
注意:(此處畫重點)
1.如果常數是個字符串,那麼使用單引號(『』)就非常重要了,比如『王者榮耀』。
2.單引號說明引號中的字符串是個常數,否則 SQL 會把王者榮耀當成列名進行查詢,但實際上數據表裡沒有這個列名,就會引起錯誤。
3.如果常數是英文字母,比如'WZRY'也需要加引號。
4.如果常數是個數字,就可以直接寫數字,不需要單引號,比如:
select 123 as platform, name from heros;
運行結果如下:
六、去除重複行
使用關鍵字distinct可以去除重複行,打個比方所有英雄只有二種:近戰和遠程。那好我們比較一下分別用distinct搜索和不加distinct搜索的效果。
去重搜索語句:select distinct attack_range, name from heros;
不去重搜索語句:select attack_range, name from heros;
效果圖如下:
去重的查詢效果如下:
不去重的查詢效果如下:
當然下面還有很多數據,只是太多了我截圖放不開。
distinct需要注意的地方:
1.DISTINCT 需要放到所有列名的前面,如果寫成SELECT name, DISTINCT attack_range FROM heros會報錯。
2.DISTINCT 其實是對後面所有列名的組合進行去重.
七、如何排序檢索數據
有時候我們需要對檢索出來的數據按照某種順序進行結果的返回,比如我們想要查詢所有的英雄,按照最大生命從高到底的順序進行排列,就需要使用 ORDER BY 子句。使用 ORDER BY 子句有以下幾個點需要掌握:
排序的列名:ORDER BY 後面可以有一個或多個列名,如果是多個列名進行排序,會按照後面第一個列先進行排序,當第一列的值相同的時候,再按照第二列進行排序,以此類推。排序的順序:ORDER BY 後面可以註明排序規則,ASC 代表遞增排序,DESC 代表遞減排序。如果沒有註明排序規則,默認情況下是按照 ASC 遞增排序。我們很容易理解 ORDER BY 對數值類型欄位的排序規則,但如果排序欄位類型為文本數據,就需要參考資料庫的設置方式了,這樣才能判斷 A 是在 B 之前,還是在 B 之後。比如使用 MySQL 在創建欄位的時候設置為 BINARY 屬性,就代表區分大小寫。非選擇列排序:ORDER BY 可以使用非選擇列進行排序,所以即使在 SELECT 後面沒有這個列名,你同樣可以放到 ORDER BY 後面進行排序。ORDER BY 的位置:ORDER BY 通常位於 SELECT 語句的最後一條子句,否則會報錯。了解了order by的使用方法之後,我們來做個練習吧。
假設我們想要顯示英雄名稱及最大生命值,按照最大生命值從高到低的方式進行排序:
SQL:SELECT name, hp_max FROM heros ORDER BY hp_max DESC ;
運行結果(69 條記錄):
如果想要顯示英雄名稱及最大生命值,按照第一排序最大法力從低到高,當最大法力值相等的時候則按照第二排序進行,即最大生命值從高到低的方式進行排序:
SQL:SELECT name, hp_max FROM heros ORDER BY mp_max, hp_max DESC
八、約束返回結果的數量
另外在查詢過程中,我們可以約束返回結果的數量,使用 LIMIT 關鍵字。比如我們想返回英雄名稱及最大生命值,按照最大生命值從高到低排序,返回 5 條記錄即可。
SQL:SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5
運行結果(5 條記錄):
小技巧:
limit 約束返回結果的數量可以減少數據表的網絡傳輸量,也可以提升查詢效率。如果我們知道返回結果只有 1 條,就可以使用LIMIT 1,告訴 SELECT 語句只需要返回一條記錄即可。這樣的好處就是 SELECT 不需要掃描完整的表,只需要檢索到一條符合條件的記錄即可返回。
九、SELECT 的執行順序
關鍵字順序不能顛倒,一旦顛倒就報錯。 SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
2.SELECT 語句的執行順序要記住。
FROM > WHERE > GROUP BY > HAVING > SELECT的欄位 > DISTINCT > ORDER BY > LIMIT
比如你寫了一個 SQL 語句,那麼它的關鍵字順序和執行順序是下面這樣的:
在 SELECT 語句執行這些步驟的時候,每個步驟都會產生一個虛擬表,然後將這個虛擬表傳入下一個步驟中作為輸入。需要注意的是,這些步驟隱含在 SQL 的執行過程中,對於我們來說是不可見的。
十、什麼情況下用 SELECT*,如何提升 SELECT 查詢效率?
首先我們不建議用seletct *。如果你僅僅是練習,或者對數據表進行探索可以這麼用,其他的地方建議你從開始就養成良好的習慣不要用它。
結尾
本章講到這裡吧,今天我對 SELECT 的基礎語法進行了講解,SELECT 是 SQL 的基礎。但不同階段看 SELECT 都會有新的體會。當你第一次學習的時候,關注的往往是如何使用它,或者語法是否正確。再看的時候,可能就會更關注 SELECT 的查詢效率,以及不同 DBMS 之間的差別。在我們的日常工作中,很多人都可以寫出 SELECT 語句,但是執行的效率卻相差很大。產生這種情況的原因主要有兩個,一個是習慣的培養,比如大部分初學者會經常使用SELECT *,而好的習慣則是只查詢所需要的列;另一個對 SQL 查詢的執行順序及查詢效率的關注,比如當你知道只有 1 條記錄的時候,就可以使用LIMIT 1來進行約束,從而提升查詢效率。