SQL 中的一些小巧但常用的關鍵字

YangAM發表於2019-03-05

前面的幾篇文章中,我們大體上介紹了 SQL 中基本的建立、查詢語句,甚至也學習了相對複雜的連線查詢和子查詢,這些基本功相信你也一定掌握的不錯,那麼本篇則著重介紹幾個技巧方面的關鍵字,能夠讓你更快更有效率的寫出一些 SQL。

起別名

在實際的專案中,有時候我們的表名、欄位名過於複雜以致於我們的 SQL 寫出來過長、過於複雜,這時候我們往往會通過起別名的方式將一些名字較長、較為複雜的欄位或是表名簡化。

我們可以使用別名(Alias)來對資料表或者列進行臨時命名,既然是別名,也就是說並不會修改原表或列的原始名稱,僅僅用於當前查詢的簡介化顯示。

給表起別名:

select * from person as p
where p.id = 1;
複製程式碼

一旦為表執行了別名,那麼本次查詢的子查詢語句中都可以直接引用別名替代原表的引用。

給列起別名:

select name as n,age as a from perosn;
複製程式碼

除了使用關鍵字 as 來給表或是列起別名外,還可以直接使用空格字元達到同樣的效果,但是個人認為要麼全部使用 as 進行別名,要麼全部使用空格進行別名,不要交叉使用使得你的 SQL 複雜又難以看懂。

消除重複記錄

有時候,我們的資料庫中會存在兩條完全一樣的資料,我們也叫做冗餘資料,當然不希望在查詢資料的時候查出來這麼些冗餘的重複資料,我們要把它們過濾掉。

LeetCode 上的一道簡單題:

有一個courses 表 ,有: student (學生) 和 class (課程)。

請列出所有超過或等於5名學生的課。

例如,表:

+---------+------------+
| student | class      |
+---------+------------+
| A       | Math       |
| B       | English    |
| C       | Math       |
| D       | Biology    |
| E       | Math       |
| F       | Computer   |
| G       | Math       |
| H       | Math       |
| I       | Math       |
+---------+------------+

應該輸出:

+---------+
| class   |
+---------+
| Math    |
+---------+
複製程式碼

你可以花個一分鐘思考一下,運用我們之前的基本功,應該是不難的。

顯然是需要用到分組的,想要統計每門課有多少人選,就得按照學科進行分組,每個分組內就是該門學科選修的學生記錄。

那麼 SQL 語句也就信手拈來了:

select class from courses
group by class
having count(student) >=5 
複製程式碼

但是你提交後在海量測試用例下,會返回給你解答錯誤的提示,不信你試試,問題出在哪?

問題就出現在冗餘資料這個邊界條件沒有被考慮,如果 A 選了兩次 Math,當我們對 Math 這個分組進行計數時就會多算一次選 Math 的人數,實際上這是不符合邏輯的,我們需要過濾掉那些重複選擇的資料記錄。

解決方案如下:

select class from courses
group by class
having count(distinct student) >=5 
複製程式碼

有些人可能看出來了,我們在 count 函式的列引數前新增了一個 distinct 關鍵字,它表示如果 student 列的值重複出現的話只計數一次。

當然,distinct 除了可以在聚合函式中使用外,也可以直接用在查詢語句的列篩選階段,例如:

//取出所有的學生,不允許重複名字的學生同時出現
select distinct name from students
複製程式碼

連線結果集

UNION 運算子可以將一個或多個 SELECT 語句的結果連線組合成一個結果集,但要求兩個或多個結果具有相同數量的列,列的資料型別相同,舉個例子:

構建一個學生表:

+----+------+----------+-------+
| id | name | uNo      | fees  |
+----+------+----------+-------+
|  1 | 張三 | 15263501 | 18000 |
|  2 | 李四 | 15263506 | 15960 |
|  3 | 王二 | 15263512 |  2500 |
+----+------+----------+-------+
複製程式碼

學生表主要有學生的姓名,學號和學費。

構建一個教師表:

+----+--------+------+--------+
| id | name   | tNo  | salary |
+----+--------+------+--------+
|  1 | 李老師 | 1001 |  10000 |
|  2 | 楊老師 | 1002 |  15000 |
|  3 | 曹老師 | 1030 |   5000 |
+----+--------+------+--------+
複製程式碼

現在有一個需求,需要拿到全校所有人的姓名和編號,包括學生和老師。一般來說,我們兩次 select 查詢就好了,但是沒法合併在一個結果集中顯示,這是一個問題。

於是我們可以使用 union 來連線兩個結果並在一張表中顯示出來:

select name,uNo from students
union
select name,tNo from teacher
複製程式碼

查詢結果:

+--------+----------+
| name   | uNo      |
+--------+----------+
| 張三   | 15263501 |
| 李四   | 15263506 |
| 王二   | 15263512 |
| 李老師 | 1001     |
| 楊老師 | 1002     |
| 曹老師 | 1030     |
+--------+----------+
複製程式碼

看起來是不是直觀了很多,除此之外的是,如果兩個結果集中存在完全重複的資料記錄,合併後的結果集中不會重複出現該資料記錄。

當然了,如果你不需要在合併結果集的時候刪除掉重複的資料行,你可以轉而使用關鍵字 UNION ALL 替代 UNION。

TOP

TOP 子句用於從一張資料表中取回前 N 個或者 X% 的記錄,但是需要注意的是,只有 SQLserver 資料庫實現是支援 TOP 的,其他資料庫則各自有各自的關鍵字作為替代,例如 MySQL 使用 LIMIT 關鍵字,Oracle 使用 ROWNUM 關鍵字。

例如:

select * from students limit 2;
複製程式碼

MySQL 資料庫取出前兩條資料,等效的 Oracle 資料庫寫法:

select * from students
rownum <= 2
複製程式碼

以上的一些關鍵字雖然逐個看起來很簡單,但有時候可能會幫上你大忙的,不要忘記使用它們!。


關注公眾不迷路,一個愛分享的程式設計師。
公眾號回覆「1024」加作者微信一起探討學習!
每篇文章用到的所有案例程式碼素材都會上傳我個人 github
https://github.com/SingleYam/overview_java
歡迎來踩!

YangAM 公眾號

相關文章