iT邦幫忙

2022 iThome 鐵人賽

1
自我挑戰組

資料庫新手入門--以PostgreSQL為例系列 第 23

Day 23 SQL條件判斷式

  • 分享至 

  • xImage
  •  

我們人生中許多時刻都在談條件,可能是跟媽媽的約定、可能是談薪水,不只在人生決策上很重要,在IT領域當中,能夠依據條件去進行不同處理的功能在許多程式語言當中絕對是必備的,資料庫查詢語言(SQL)雖然屬性上與一般程式較為不同,不過也有撰寫條件式的功能,語法略為不同。

  • 我們可以使用 CASE STATEMENT 只在滿足某些條件時才執行SQL代碼。
  • 與其他程式語言中的 IF/ELSE STATEMENT 非常相似。
  • 由於CASEis 是一個表達式,因此您可以在任何可以使用表達式的地方使用它,例如SELECT、WHEREHAVING

先寫入範例資料,由於本文重點在SQL條件判斷式,為了方便示範SQL條件判斷式,下面所使用的資料表與資料不會考慮正規化的內容,或可參考Day15 為什麼要Normalization,自己建立範例練習。

CREATE TABLE orders (
	customer_id INT,
	customer_level INT,
	course_name VARCHAR(255),
	course_time INTERVAL,
	price INT
);

INSERT INTO orders(customer_id,customer_level, course_name,course_time,price)
VALUES (1,1,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(2,1,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(3,1,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(4,1,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(5,2,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(6,2,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(6,2,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(6,2,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(7,3,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(8,3,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(9,3,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(10,3,'PostgreSQL新手入門第一堂課', '17 hours 30 minutes', 2599),
(11,1,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(12,2,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(13,2,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(14,3,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(15,1,'PHP新手入門網站開發', '12 hours 17 minutes', 1799),
(16,1,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(17,2,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(18,3,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(19,4,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999),
(20,5,'JavaScript新手入門轉職利器', '21 hours 02 minutes', 2999);

基礎用法

這是最簡單最基礎的用法,如果看到什麼就輸出什麼,假設為了增強客戶的榮譽心,我們將花越多錢的客戶給予越帥氣的名稱,絕對不是想騙客戶口袋裡的錢錢 : )

-- 假設這是一間稱為程式魔法學院的線上課程網站,給個帥帥的名稱有助於沉浸式學習。(!?)
SELECT customer_id AS 使用者編號,
	   CASE WHEN customer_level=1 THEN '初心者'
	   		WHEN customer_level=2 THEN '魔法師'
				WHEN customer_level=3 THEN '巫師'
	   		ELSE '賢者'
	   END AS 使用者職業
FROM orders;

條件過濾

我們有時候會在不同條件下,關注不一樣的重點,例如客戶等級1的時候,我們想找出有多少第一次買線上課程就願意花2000元以上的課程,接著假設客戶等級大於1是代表已經購買不只一堂課的線上課程的客戶,這些客戶願意買15小時以下的課程有多少意願,雖然這是兩件事情,但我們可以透過CASE STATEMENT 一次處理起來。

謎之音 : 抓出願意買2000元以上課程的新用戶跟願意買較短課程的老用戶,可以用來決策課程價格定位以及確認課程長度多短可以被購買(開源跟節流)。

SELECT *	
FROM orders 
WHERE CASE 
		WHEN 
			customer_level = 1
		THEN 
			price > 2000
		ELSE 
			course_time < '15:00:00'
		END
ORDER BY customer_level,customer_id;

搭配聚合函數

假設使用者等級是一等初心者,價格一率打85折,那麼可以透過CASE來計算實際總收入,如果是初心者就必須算標價的85折,其他則原價計算。

SELECT 
SUM(
	CASE WHEN customer_level = 1
		THEN ROUND(price * 0.85)
		ELSE price
	END
) AS 總收入
FROM orders

使用COALESCE處理NULL

COALESCE : 不限數量的傳入參數,依序找不是NULL的參數,如果找到就回傳值,通常被運用於如果NULL則回傳什麼值,這種情境下比 CASE STATEMENT 更為簡潔。

假設有一間滷味攤,經營策略是買70元送10元,以此類推,那麼我們來看每筆交易狀況。

CREATE TABLE luwei(
	id SERIAL PRIMARY KEY,
	price NUMERIC NOT NULL,
	discount NUMERIC
);

INSERT INTO luwei (price, discount)
VALUES
	(70, 10),
	(85, 10),
	(45, NULL),
	(75, 10)
	(140, 20);

如果我們使用交易價減掉折價,會發生沒有折價的那筆會出現問題。

-- NULL的資料,相減後仍是NULL。(此為非預期的異常)
SELECT (price - discount) AS real_price
FROM luwei;

因此我們可以使用 COALESCE 來處理 NULL,如果是NULL,就往右找參數,找到0並回傳。

SELECT (price - COALESCE(discount,0)) AS real_price
FROM luwei;

使用NULLIF防止除以0的錯誤

CREATE TABLE employees (
	name VARCHAR(255),
	type VARCHAR(255)
);

INSERT INTO employees (name,type)
VALUES ('王大空','專任助理'),
('陳大天','專任助理'),
('廖小明','博士後研究員');

假設我們有一個需求卡博後人數與專任助理相比不能超過50%,可以用以下的語法去算。

SELECT 
ROUND(
(SUM(CASE WHEN TYPE = '博士後研究員' THEN 1 ELSE 0 END)::NUMERIC /
 SUM(CASE WHEN TYPE = '專任助理' THEN 1 ELSE 0 END)::NUMERIC * 100
),2) || '%' AS 博後人數為專助人數的幾趴
FROM employees

不過如果兩個專任助理都離職了,那麼只剩下一個博後跟零個專任助理,上面這個語句就會遇到1/0的錯誤,資料庫就會噴錯 ERROR: division by zero,我們可以過NULLIF去判斷如果除數等於0就回傳NULL,這樣至少可以保證程式可以繼續執行下去。

SELECT 
ROUND(
	( SUM(CASE WHEN TYPE = '博士後研究員' THEN 1 ELSE 0 END)::NUMERIC /
	  NULLIF(SUM(CASE WHEN TYPE = '專任助理' THEN 1 ELSE 0 END)::NUMERIC * 100 ,0)
	)
,2) || '%' AS 博後人數為專助人數的幾趴
FROM employees

上一篇
Day 22 日期與時間
下一篇
Day 24 妥妥的才算交易
系列文
資料庫新手入門--以PostgreSQL為例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言