[SQL 入門與面試實戰] 1. 一切都從 SELECT…FROM…

沈哲宇
數據原點
Published in
13 min readJan 22, 2024

歡迎來到 SQL 入門與面試實戰系列!!!

各位朋友將學會最常使用的 SQL 語法,幫助你在數據 / 商業分析師的面試中順利過關斬將!
若還沒有看過前導文章的請到:
[SQL 入門與面試實戰系列] 0. 系列介紹 & 環境使用

還沒下載數據庫與 Colab 檔案到您的 Google 雲端請到這邊下載:
[SQL 入門與面試實戰系列] Colab Notebooks

準備好的朋友們,就讓我們開始 SQL 的第一步:SELECT…FROM…
[SQL 入門與面試實戰系列] 1_基本查詢語法.ipynb

  • SELECT…FROM…:從數據庫中選取資料
  • ORDER BY:排序數據
  • DISTINCT:篩選獨特值,去除重複項
  • WHERE:篩選符合指定條件的資料
  • SELECT…FROM…:從數據庫中選取資料

SQL 簡單說,其實就是從數據庫抓取資料表的語法。我們可以將數據庫想象成一個存放多張資料表的地方,而資料表其實就類似我們熟悉的 Excel 檔案。橫向的第一列為欄位名稱,而從第二列開始往下則是具體數據的部分。
※小知識:通常我們會將橫向的資料稱為列 (rows)、直向的資料稱為欄 (columns)。

首先,讓我們看一下我們使用的範例數據庫 (chinook.db) 包含了哪些資料表:

(由 SQLite 提供的數據庫,圖片來源)

我們所使用的數據庫包含了 11 張資料表,例如圖中右上角名為 customers 的資料表;這張資料表紀錄了顧客資料,包含多個欄位比如會員編號(CustomerId)、顧客的名字(FirstName)和姓氏(LastName)等。
customers 資料表的部分內容如下 (顯示前 5 列資料) :

現在,讓我們用 SQL 語法來查看 customers 資料表。SQL 最基本的查詢語法就是:

SELECT `欄位名稱` FROM `資料表名`

這就是我們寫 SQL 語法的起手式:從某張資料表 (FROM 資料表) 選取需要的欄位 (SELECT 欄位 );如果想查看所有資料表的所有欄位,則使用星號 (*) 表示選擇所有欄位:

SELECT * FROM customers

登愣!customers 資料表就被完整的叫出來了!

在我們大展身手對資料表進行分析之前,一定要先透過 SELECT…FROM…,了解使用的資料表包含了哪些欄位、每個欄位代表什麼意思、紀錄的數值是什麼等。如果我們不知道這張表紀錄的什麼,後續一切的分析都可能是徒勞無功!

如果我們只對某些特定欄位感興趣,則可以在 SELECT 後面指定這些欄位。例如我們只想查看 customers 資料表裡的 CustomerIdFirstNameLastName 三個欄位的資料:

SELECT CustomerId, FirstName, LastName FROM customers

此外,如果我們覺得資料表有太多列,可以在查詢語句的最後面,使用 LIMIT + 數字 來限制顯示的列數。例如,僅展示 customers 表中的前5條數據:

SELECT CustomerId, FirstName, LastName FROM customers
LIMIT 5
  • ORDER BY:排序數據

在提取資料表後,我們經常會選擇一個或多個欄位的數據進行排序,就像是整理資料的順序,讓我們可以更有效地觀察數據。比如在商業分析中,我們可能會根據訂單的日期進行排序,再將同一天的訂單根據銷售額進行排序,以便查看每天的銷售狀況。
ORDER BY 的基本語法如下:

SELECT `欄位名稱` FROM `資料表名`
ORDER BY `欄位名稱` ASC/DESC

customers 資料表原本是根據 CustomerId 欄位進行排序,假設我們想根據顧客的姓氏 (LastName) ,來整理 customers 表的順序,我們可以這樣寫:

SELECT * FROM customers
ORDER BY LastName

可以看到現在資料是以 LastName 欄位,按照字母從 A 開始一直到 Z 排序。

排序有分為升序(ASC)與降序(DESC)。升序指的是數字從小到大、從低到高或從 A 到 Z 的順序;降序則是相反,即從大到小、從高到低或從 Z 到 A 排列。我們在使用 ORDER BY 如果不指定,預設就是升序排序。
假設我們想按照顧客的姓氏從 Z 到 A 降序(即降序)排列,可以在 ORDER BY 欄位後面加上 DESC:

SELECT * FROM customers
ORDER BY LastName DESC

最後,當我們需要根據多個欄位來排序時,可以按照優先順序列出這些欄位。比方我們想按姓氏排序,然後在相同姓氏的情況下按名字排序,可以使用以下語句:

SELECT * FROM customers 
ORDER BY LastName, FirstName

這樣會先根據顧客的姓氏(LastName)進行字母升序排列;對於擁有相同姓氏的顧客,則會根據他們的名字(FirstName)進行字母升序排列。

  • DISTINCT:篩選獨特值,去除重複項

有時候在分析資料表時,我們可能對某個欄位中的獨特(不重複)值感興趣。比如說我們想知道 customers 資料表中的顧客包含了哪些不同的國籍,這時 DISTINCT 就派上用場了。要篩選出某個欄位的不重複值,我們可以這樣將 DISTINCT 放在指定欄位前:

SELECT DISTINCT `欄位名` FROM `表格名`

比如想知道顧客包含了哪些不同的國籍 (Country 欄位),我們可以這樣寫:

SELECT DISTINCT Country FROM customers

這條指令會列出 customers 資料表中所有不重複的國籍。

通常情況下,我們使用 DISTINCT 時只會專注於一個欄位,以找出該欄位的所有不同值。比如說,我們不太可能在 DISTINCT Country 後面再加上其他欄位,因為那樣做不會達到我們想要的去除重複值的效果(變成尋找不同的國籍與其他欄位的組合)。

  • WHERE:篩選符合指定條件的資料

從數據庫叫出整張資料表後,通常我們只對符合特定條件的資料感興趣。這時候我們會使用 WHERE 作為篩選工具,讓我們指定條件,並且只顯示那些符合條件的數據。
WHERE 的語法如下:

SELECT * FROM `表格名`
WHERE (`欄位名` = '特定值') AND/OR (`欄位名` = '特定值')

我們先寫出 SELECT…FROM… 基本查詢語句,然後加上 WHERE 和我們的篩選條件。比如我想要從 customers 表當中,篩選出來自美國 ('USA') 的顧客,我們可以這樣寫:

SELECT * FROM customers 
WHERE Country = 'USA'

當然除了篩選「等於」某個值的資料外,我們也可以篩選出「不等於」某個值的資料。如果我們想找出「不是」來自美國的顧客,可以使用不等於符號 (<>):

SELECT * FROM customers 
WHERE Country <> 'USA'

假設我們想要同時設定多個條件,可以搭配 AND (且)、OR (或) 來連接條件。當所有條件都需要符合時使用 AND,例如我們想要篩選出國籍為美國,州份是加州 ('CA') 的顧客資料 (兩個條件都要滿足):

SELECT * FROM customers 
WHERE Country = 'USA' AND State = 'CA'

如果多個條件中只要一個條件滿足即可則使用 OR,例如我們想要篩選出來自美國加拿大 ('Canada') 的顧客資料 (任一個條件滿足即可):

SELECT * FROM customers 
WHERE Country = 'USA' OR Country = 'Canada'

另外,假設我們是想對同一個欄位上指定多個可能的值,可以更簡潔地使用 IN。比如說上面找出來自美國或加拿大的顧客的案例可以這樣寫:

SELECT * FROM customers 
WHERE Country IN ('USA', 'Canada')

相反地 NOT IN 則適用於排除特定值,也就是「不」來自美國與加拿大的顧客:

SELECT * FROM customers 
WHERE Country NOT IN ('USA', 'Canada')

WHERE 子句非常靈活,它不僅可以用於文字類型的數據,還可以用於數字、日期等多種類型的數據。實際商業面常見的情境包括篩選某段時間區間的訂單、訂單金額達於某數字等。
(※補充:時間欄位通常會需要搭配時間函數才能進行運算,這點我們在第四章會有更深的介紹)

如果我們想要設置的篩選條件是數值、日期這些具有連續性、可以比大小屬性的話,我們也可以使用 > (大於) 、< (小於) 等比較運算符號相關的符號。例如我們想要篩選會員編號 (CustomerId) 介於 5 到 10 (包含 5 和 10) 的顧客,相信聰明的你已經知道怎麼寫了:

SELECT * FROM customers 
WHERE CustomerId >= 5 AND CustomerId <= 10

如果條件是篩選出在某個特定範圍內的數據時,我們可以使用 BETWEEN。使用 BETWEEN 要記得它包含範圍的起始和終止值。例如上面的例子可以直接寫成:

SELECT * FROM customers 
WHERE CustomerId BETWEEN 5 AND 10

最後,如果沒有任何資料符合我們在 WHERE 子句設定的條件值,那麼查詢將不會返回任何資料 (SQL 語句本身並沒有問題所以不會跑出錯誤,只是沒有資料符合設定的條件而已)。比方說我想找出來自台灣 ('Taiwan') 的顧客,但 customers 表剛好沒有,因此查詢結果將是空的:

SELECT * FROM customers
WHERE Country = 'Taiwan'

本章快速總結:

  1. SELECT…FROM…:是 SQL 中最基本的查詢方式。指定要查看的欄位,並從指定的表中提取這些欄位的數據。
  2. ORDER BY:對查詢結果進行排序,可根據一個或多個欄位進行升序或降序排列,如按字母順序或數字大小。
  3. DISTINCT:篩選出欄位中獨特的值,去除重複項。
  4. WHERE:根據特定條件篩選數據,只顯示符合這些條件的資料。WHERE 支援多種條件 (如數值範圍、特定文字) 和邏輯運算符 (如 AND、OR 和 NOT)。

最後再和大家說明一下 SQL 一些基本的撰寫規則。這些規則幫助你寫出更清晰與正確的程式碼,也讓其他人更容易理解你的 SQL 腳本。

  1. SQL 用大寫:SQL 其實是不區分大小寫的,例如 SELECT, Select, 和 select 在 SQL 中都是可以的,只是普遍我們會使用大寫來寫 SQL 提高可讀性。
-- 這些語句都可以跑、功能也相同,但使用大寫更易於閱讀
SELECT * FROM customers;
select * from customers;
SeLeCT * fRoM customers;

2. 欄位和字串值的區別:在 SQL 中對於欄位名稱和表名,我們通常不需要加引號。不過實際案例可能會遇到中文、特殊字符、或剛好名稱與 SQL 函數同名的狀況,這時候就需要對欄位名稱與表名加上雙引號 (”) 或反引號 (`) (反引號就是鍵盤數字 1 左邊的那個)。而在處理字串值時,必須將它們放在單引號 (’) 裡面。

-- 正確使用引號
-- 反引號 (`) 或雙引號 (") 用來標識資料表名和欄位名稱。具體用哪一個取決於撰寫 SQL 的環境
-- 單引號 (') 用於標識字串常數
SELECT * FROM `customers` WHERE `FirstName` = 'John';
SELECT * FROM "customers" WHERE "FirstName" = 'John';

-- 錯誤:不應該將字串用雙引號包圍
SELECT * FROM customers WHERE FirstName = "John";

3. 換行與排版:隨著我們的 SQL 語句越來越長,適當的換行與排版可以幫助自己和他人更容易閱讀和理解。例如我們可以在每個新的子句開始時換行 (FROM、WHERE、ORDER BY 等),將每一個部分都清晰分開。此外適當的縮排也有助於強調子句的層次結構,例如當選取的欄位很多時,我們可以在換行之後再按 Tab 鍵,將多個欄位放在同一個層次對齊。
(排版是準則,重點是要讓語法容易閱讀。大家可以寫好完整的 SQL 語句後丟到 Chat-GPT 幫你修改排版。)

SELECT FirstName, LastName, Country FROM customers
WHERE Country = 'USA' AND State = 'CA'
ORDER BY LastName;

-- 使用換行和縮排來提高可讀性
SELECT
FirstName,
LastName,
Country
FROM
customers
WHERE
Country = 'USA' AND
State = 'CA'
ORDER BY
LastName;

恭喜你完成第一章了!相信經過這一章的練習,大家對 SQL 都有初步的認識,是不是很簡單呢?

(真的很簡單)

--

--

沈哲宇
數據原點

現任電商商業分析師。 曾任銀行數據分析師、台大資料分析社專案長。 有任何問題歡迎聯繫:brianshen57@gmail.com