1. 程式人生 > 其它 >SQL基礎-第6章 函式、謂詞、CASE表示式

SQL基礎-第6章 函式、謂詞、CASE表示式

6-1 各種各樣的函式

函式的種類

函式,就是輸入某一值得到相應輸出結果的功能,輸入值稱為引數(parameter),輸出值稱為返回值

  • 算術函式(用來進行數值計算的函式)
  • 字串函式(用來進行字串操作的函式)
  • 日期函式(用來進行日期操作的函式)
  • 轉換函式(用來轉換資料型別和值的函式)
  • 聚合函式(用來進行資料聚合的函式)
-- DDL :建立表
CREATE TABLE SampleMath
(m NUMERIC (10,3),
n INTEGER,
p INTEGER);

-- DML :插入資料
START TRANSACTION; 
INSERT INTO SampleMath(m, n, p) VALUES (500, 0, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (-180, 0, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, NULL, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 7, 3);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 5, 2);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 4, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (8, NULL, 3);
INSERT INTO SampleMath(m, n, p) VALUES (2.27, 1, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (5.555,2, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 1, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (8.76, NULL, NULL);
COMMIT;

SELECT * FROM SampleMath;

算術函式

  • +(加法)

  • -(減法)

  • *(乘法)

  • /(除法)

  • ABS——絕對值 ABS(數值)

-- 計算數值的絕對值
SELECT m,
ABS(m) AS abs_col
FROM SampleMath;
  • MOD——求餘 MOD(被除數,除數)
-- 計算除法( n ÷ p)的餘數
SELECT n, p,
MOD(n, p) AS mod_col
FROM SampleMath;
  • ROUND——四捨五入 ROUND(物件數值,保留小數的位數)
-- 對m列的數值進行n列位數的四捨五入處理
SELECT m, n,
ROUND(m, n) AS round_col
FROM SampleMath;

字串函式

  • CONCAT函式 CONCAT函式(字串1, 字串2)
-- 拼接字串
SELECT str1, str2, str3,
CONCAT(str1, str2, str3) AS str_concat
FROM SampleStr;
  • LENGTH——字串長度 LENGTH(字串)
-- 計算字串長度
SELECT str1,
LENGTH(str1) AS len_str
FROM SampleStr;
  • LOWER——小寫轉換 LOWER(字串)
-- 大寫轉換為小寫
SELECT str1,
LOWER(str1) AS low_str
FROM SampleStr;
  • REPLACE——字串的替換
    • REPLACE(物件字串,替換前的字串,替換後的字串)
-- 替換字串的一部分
SELECT str1, str2, str3,
REPLACE(str1, str2, str3) AS rep_str
FROM SampleStr;
  • SUBSTRING——字串的擷取
    • SUBSTRING(物件字串 FROM 擷取的起始位置 FOR 擷取的字元數)
-- 截取出字串中第3位和第4位的字元
SELECT str1,
SUBSTRING(str1 FROM 3 FOR 2) AS sub_str
FROM SampleStr;
  • UPPER——大寫轉換 UPPER(字串)
-- 將小寫轉換為大寫
SELECT str1,
UPPER(str1) AS up_str
FROM SampleStr
WHERE str1 IN ('ABC', 'aBC', 'abc', '山田');

日期函式

  • CURRENT_DATE——當前日期
-- 獲得當前日期
SELECT CURRENT_DATE;
  • CURRENT_TIME——當前時間
-- 取得當前時間
SELECT CURRENT_TIME;
  • CURRENT_TIMESTAMP——當前日期和時間
-- 取得當前日期和時間
SELECT CURRENT_TIMESTAMP;
  • EXTRACT——擷取日期元素
    • EXTRACT(日期元素 FROM 日期)
-- 擷取日期元素
SELECT CURRENT_TIMESTAMP,
EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS year,
EXTRACT(MONTH FROM CURRENT_TIMESTAMP) AS month,
EXTRACT(DAY FROM CURRENT_TIMESTAMP) AS day,
EXTRACT(HOUR FROM CURRENT_TIMESTAMP) AS hour,
EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS minute,
EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second;

轉換函式

  • CAST——型別轉換
    • CAST(轉換前的值 AS 想要轉換的資料型別)
  • COALESCE——將NULL轉換為其他值
    • COALESCE(資料1,資料2,資料3……)
-- 將字串型別轉換為數值型別
SELECT CAST('0001' AS SIGNED INTEGER) AS int_col;

-- 將字串型別轉換為日期型別
SELECT CAST('2009-12-14' AS DATE) AS date_col;

- 將NULL轉換為其他值
SELECT COALESCE(NULL, 1) AS col_1,
COALESCE(NULL, 'test', NULL) AS col_2,
COALESCE(NULL, NULL, '2009-11-01') AS col_3;

-- 使用SampleStr表中的列作為例子
SELECT COALESCE(str2, 'NULL')
FROM SampleStr;

6-2 謂詞

什麼是謂詞

謂詞就是需要滿足特定條件的函式,該條件就是返回值是真值

LIKE謂詞——字串的部分一致查詢

% 是代表“0 字元以上的任意字串”的特殊符號

_(下劃線)代表了“任意 1 個字元”

-- DDL :建立表
CREATE TABLE SampleLike
( strcol VARCHAR(6) NOT NULL,
PRIMARY KEY (strcol));

-- DML :插入資料
START TRANSACTION; 
INSERT INTO SampleLike (strcol) VALUES ('abcddd');
INSERT INTO SampleLike (strcol) VALUES ('dddabc');
INSERT INTO SampleLike (strcol) VALUES ('abdddc');
INSERT INTO SampleLike (strcol) VALUES ('abcdd');
INSERT INTO SampleLike (strcol) VALUES ('ddabc');
INSERT INTO SampleLike (strcol) VALUES ('abddc');
COMMIT;

-- 使用LIKE進行前方一致查詢
SELECT *
FROM SampleLike
WHERE strcol LIKE 'ddd%';

-- 使用LIKE進行中間一致查詢
SELECT *
FROM SampleLike
WHERE strcol LIKE '%ddd%';

-- 使用LIKE進行後方一致查詢
SELECT *
FROM SampleLike
WHERE strcol LIKE '%ddd';

-- 使用LIKE和_(下劃線)進行後方一致查詢
SELECT *
FROM SampleLike
WHERE strcol LIKE 'abc__';

-- 查詢“abc+任意3個字元”的字串
SELECT *
FROM SampleLike
WHERE strcol LIKE 'abc___';

BETWEEN謂詞——範圍查詢

-- 選取銷售單價為100~ 1000日元的商品
SELECT product_name, sale_price
FROM Product
WHERE sale_price BETWEEN 100 AND 1000;

-- 選取出銷售單價為101 ~ 999日元的商品
SELECT product_name, sale_price
FROM Product
WHERE sale_price > 100
AND sale_price < 1000;

IS-NULL、IS-NOT-NULL——判斷是否為NULL

-- 選取出進貨單價( purchase_price)為NULL的商品
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IS NULL;

-- 選取進貨單價( purchase_price)不為NULL的商品
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IS NOT NULL;

IN謂詞——OR的簡便用法

使用IN 和 NOT IN 時是無法選取出NULL 資料的

-- 通過OR指定多個進貨單價進行查詢
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price = 320
OR purchase_price = 500
OR purchase_price = 5000;

-- 通過IN來指定多個進貨單價進行查詢
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IN (320, 500, 5000);

-- 使用NOT IN進行查詢時指定多個排除的進貨單價進行查詢
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price NOT IN (320, 500, 5000);

使用子查詢作為IN謂詞的引數

-- 建立ShopProduct(商店商品)表的CREATE TABLE語句
CREATE TABLE ShopProduct
(shop_id CHAR(4) NOT NULL,
shop_name VARCHAR(200) NOT NULL,
product_id CHAR(4) NOT NULL,
quantity INTEGER NOT NULL,
PRIMARY KEY (shop_id, product_id))
DEFAULT CHARSET=utf8;

-- 向ShopProduct表中插入資料的INSERT語句

START TRANSACTION; 
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '東京', '0001', 30);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '東京', '0002', 50);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '東京', '0003', 15);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0002', 30);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0003', 120);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0004', 20);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0006', 10);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0007', 40);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0003', 20);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0004', 50);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0006', 90);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0007', 70);
INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000D', '福岡', '0001', 100);
COMMIT;

-- 使用子查詢作為IN的引數
-- 取得“在大阪店銷售的商品的銷售單價”
SELECT product_name, sale_price
FROM Product
WHERE product_id IN (SELECT product_id
	FROM ShopProduct
	WHERE shop_id = '000C');

-- 使用子查詢作為NOT IN的引數
-- 在東京店(000A)以外銷售的商品的銷售單價
SELECT product_name, sale_price
FROM Product
WHERE product_id NOT IN (SELECT product_id
FROM ShopProduct
WHERE shop_id = '000A');

EXIST謂詞

謂詞的作用就是“判斷是否存在滿足某種條件的記錄”

-- 使用 EXIST選取出“大阪店在售商品的銷售單價”
SELECT product_name, sale_price
FROM Product AS P 
WHERE EXISTS (SELECT *
	FROM ShopProduct AS SP 
	WHERE SP.shop_id = '000C'
	AND SP.product_id = P.product_id);

-- 這樣的寫法也能得到相同的結果
SELECT product_name, sale_price
FROM Product AS P 
WHERE EXISTS (SELECT 1 -- 這裡可以書寫適當的常數
FROM ShopProduct AS SP 
WHERE SP.shop_id = '000C'
AND SP.product_id = P.product_id);

-- 使用NOT EXIST讀取出“東京店在售之外的商品的銷售單價”
SELECT product_name, sale_price
FROM Product AS P 
WHERE NOT EXISTS (SELECT *
FROM ShopProduct AS SP
WHERE SP.shop_id = '000A'
AND SP.product_id = P.product_id);

6-3 CASE表示式

什麼是CASE表示式

一種進行運算的功能

CASE表示式的語法

CASE WHEN <求值表示式> THEN <表示式>
WHEN <求值表示式> THEN <表示式>
WHEN <求值表示式> THEN <表示式>
...
ELSE <表示式>
END

CASE表示式的使用方法

CONCAT("A : ",product_type)

簡單CASE表示式

CASE <表示式>
WHEN <表示式> THEN <表示式>
WHEN <表示式> THEN <表示式>
WHEN <表示式> THEN <表示式>
.
.
.
ELSE <表示式>
END
-- 通過CASE表示式將A ~ C的字串加入到商品種類當中
SELECT product_name,
CASE WHEN product_type = '衣服'
THEN CONCAT("A : ",product_type)
WHEN product_type = '辦公用品'
THEN CONCAT("B : ",product_type)
WHEN product_type = '廚房用具'
THEN CONCAT("C : ",product_type)
ELSE NULL
END AS abc_product_type
FROM Product;

-- 通常使用GROUP BY也無法實現行列轉換
SELECT product_type,
SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type;

使用CASE表示式進行行列轉換
-- 對按照商品種類計算出的銷售單價合計值進行行列轉換
SELECT SUM(CASE WHEN product_type = '衣服'
THEN sale_price ELSE 0 END) AS sum_price_clothes,
SUM(CASE WHEN product_type = '廚房用具'
THEN sale_price ELSE 0 END) AS sum_price_kitchen,
SUM(CASE WHEN product_type = '辦公用品'
THEN sale_price ELSE 0 END) AS sum_price_office
FROM Product;

-- 使用簡單CASE表示式的情況
SELECT product_name,
CASE product_type
WHEN '衣服' THEN CONCAT("A : ",product_type)
WHEN '辦公用品' THEN CONCAT("B : ",product_type)
WHEN '廚房用具' THEN CONCAT("C : ",product_type)
ELSE NULL
END AS abc_product_type
FROM Product;

-- 使用 CASE表示式的特定語句將字串A ~ C新增到商品種類中
-- MySQL中使用IF代替CASE表示式
SELECT product_name,
IF( IF( IF(product_type = '衣服',
CONCAT('A : ', product_type), NULL)
IS NULL AND product_type = '辦公用品',
CONCAT('B : ', product_type),
IF(product_type = '衣服',
CONCAT('A : ', product_type), NULL))
IS NULL AND product_type = '廚房用具',
CONCAT('C : ', product_type),
IF( IF(product_type = '衣服',
CONCAT('A: ', product_type), NULL)
IS NULL AND product_type = '辦公用品',
CONCAT('B : ', product_type),
IF(product_type = '衣服',
CONCAT('A : ', product_type),
NULL))) AS abc_product_type
FROM Product;

練習題

6.1 對本章中使用的 Product(商品)表執行如下 2 條 SELECT 語句,能夠得到什麼樣的結果呢?

①
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price NOT IN (500, 2800, 5000);
②
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price NOT IN (500, 2800, 5000, NULL);

①的答案

product_name purchase_price
打孔器 320
擦菜板 790

②的答案:無法取出任何記錄

6.2 按照銷售單價( sale_price)對練習 6.1 中的 Product(商品)表中的商品進行如下分類。

  • 低檔商品:銷售單價在1000日元以下(T恤衫、辦公用品、叉子、擦菜板、 圓珠筆)
  • 中檔商品:銷售單價在1001日元以上3000日元以下(菜刀)
  • 高檔商品:銷售單價在3001日元以上(運動T恤、高壓鍋)
    請編寫出統計上述商品種類中所包含的商品數量的 SELECT 語句,結果如下所示。

執行結果

low_price mid_price high_price
5 1 2
SELECT 
SUM(CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END) as low_price, 
SUM(CASE WHEN sale_price > 1000 AND sale_price <= 3000 THEN 1 ELSE 0 END) as mid_price, 
SUM(CASE WHEN sale_price > 3000 THEN 1 ELSE 0 END) as high_price
FROM Product;