學習SQL【8】-謂詞和CASE表達式

學習SQL【8】-謂詞和CASE表達式

來自專欄 Python愛好者

謂詞

什麼是謂詞

謂詞就是返回值為真值的函數。對於通常的函數來說,返回值有可能是數字、字元串和日期等,但是謂詞的返回值全部是真值。這也是謂詞和函數的最大區別。

謂詞主要有以下幾種:

  • LIKE
  • BETWEEN
  • IS NULL、IS NOT NULL
  • IN
  • EXISTS

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

截止目前,我們使用字元串作為查詢條件的例子使用的都是=。這裡的=只有在字元串完全一致時才為真。與之相反,LIKE謂詞更加模糊一些,當需要進行字元串的部分一致查詢時需要使用該謂詞。

部分一致大體可以分為前方一致、中間一致和後方一致三種類型。接下來就讓我們看一看具體示例吧。

首先,我們先創建一張用作示例的表:

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

向表中插入數據

--插入數據 BEGIN TRANSACTION;BEGIN INSERT INTO SampleLike VALUES (abcddd);INSERT 0 1 INSERT INTO SampleLike VALUES (dddabc);INSERT 0 1 INSERT INTO SampleLike VALUES (abdddc);INSERT 0 1 INSERT INTO SampleLike VALUES (abcdd);INSERT 0 1 INSERT INTO SampleLike VALUES (ddabc);INSERT 0 1 INSERT INTO SampleLike VALUES (abddc);INSERT 0 1 COMMIT;COMMIT

確認一下我們創建的表的內容:

SELECT * FROM SampleLike;

執行結果:

strcol-------- abcddd dddabc abdddc abcdd ddabc abddc(6 行記錄)

前方一致查詢

使用Like進行前方一致查詢

SELECT * FROM SampleLike WHERE strcol LIKE ddd%;

執行結果:

strcol-------- dddabc(1 行記錄)

其中的%代表「0字元以上的任意字元」的特殊符號,上例表示「以ddd開頭的所有字元」。

中間一致查詢

使用LIKE進行中間一致查詢

SELECT * FROM SampleLike WHERE strcol LIKE %ddd%;

執行結果:

strcol-------- abcddd dddabc abdddc(3 行記錄)

在字元串的起始和結束位置加上%,就能取出「包含ddd的字元串」。

後方一致查詢

使用LIKE進行後方一致查詢

SELECT * FROM SampleLike WHERE strcol LIKE %ddd;

執行結果:

strcol-------- abcddd(1 行記錄)

此外,我們還可以使用_(下劃線)來代替%,與%不同的是,它代表「任意一個字元」,下面我們就來嘗試一下:

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

執行結果:

strcol-------- abcdd(1 行記錄)

再舉個例子:

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

執行結果:

strcol-------- abcddd(1 行記錄)

BETWEEN謂詞—範圍查詢

使用BETWEEN可以進行範圍查詢。該謂詞與其他謂詞或者函數不同的是它使用了3個參數。

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

執行結果:

product_name | sale_price--------------+------------ T | 1000 打孔器 | 500 叉子 | 500 擦菜板 | 880 圓珠筆 | 100(5 行記錄)

BETWEEN的特點就是結果會包含100和1000這兩個臨界值。如果不想讓結果包含臨界值,那就必須使用<和>。

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

執行結果:

product_name | sale_price--------------+------------ 打孔器 | 500 叉子 | 500 擦菜板 | 880(3 行記錄)

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

為了選取某些值為NULL的列的數據,不能使用=,而只能使用特定的謂詞IS NULL。

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

執行結果:

product_name | purchase_price--------------+---------------- 叉子 | 圓珠筆 |(2 行記錄)

與之相反,如果選取NULL以外的數據,需要使用謂詞IS NOT NULL。

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

執行結果:

product_name | purchase_price--------------+---------------- T | 500 打孔器 | 320 運動T | 2800 菜刀 | 2800 高壓鍋 | 5000 擦菜板 | 790(6 行記錄)

IN謂詞—OR的簡便用法

通過OR指定多個進貨單價進行查詢:

SELECT product_name, purchase_price FROM Product WHERE purchase_price = 320 OR purchase_price = 500 OR purchase_price = 5000;

執行結果:

product_name | purchase_price--------------+---------------- T | 500 打孔器 | 320 高壓鍋 | 5000(3 行記錄)

我們使用IN 謂詞來替換上述SQL語句:

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

執行結果:

product_name | purchase_price--------------+---------------- T | 500 打孔器 | 320 高壓鍋 | 5000(3 行記錄)

反之,否定形式可以使用NOT IN來實現:

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

執行結果:

product_name | purchase_price--------------+---------------- 運動T | 2800 菜刀 | 2800 擦菜板 | 790(3 行記錄)

注釋:使用IN 和NOT IN 時是無法取出NULL數據的,NULL終究是需要使用IS NULL和IS NOT NULL來進行判斷。

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

IN謂詞和子查詢

IN謂詞(NOT IN謂詞)具有其他謂詞所沒有的用法,那就是可以使用子查詢來作為其參數。子查詢在之前已經學過,就是SQL內部生成的表。

為了掌握更詳盡的使用方法,我們再創建一張新表:

--創建ShopProduct(商店商品)表的CREATE TABLE語句 CREATE TABLE ShopProduct ( shop_id CHAR(4) NOT NULL, shop_name VARCHAR(200) NOT NULL, product_id CHAR(4) NOT NULL, quantit INTEGER NOT NULL, PRIMARY KEY(shop_id, product_id));

向表ShopProduct中插入數據

--向表ShopProduct中插入數據的INSERT語句 BEGIN TRANSACTION;BEGIN INSERT INTO ShopProduct VALUES(000A, 成華區, 0001, 30);INSERT 0 1 INSERT INTO ShopProduct VALUES(000A, 成華區, 0002, 50);INSERT 0 1 INSERT INTO ShopProduct VALUES(000A, 成華區, 0003, 15);INSERT 0 1 INSERT INTO ShopProduct VALUES(000B, 金牛區, 0002, 30);INSERT 0 1 INSERT INTO ShopProduct VALUES(000B, 金牛區, 0003, 120);INSERT 0 1 INSERT INTO ShopProduct VALUES(000B, 金牛區, 0004, 20);INSERT 0 1 INSERT INTO ShopProduct VALUES(000B, 金牛區, 0006, 10);INSERT 0 1 INSERT INTO ShopProduct VALUES(000B, 金牛區, 0007, 40);INSERT 0 1 INSERT INTO ShopProduct VALUES(000C, 武侯區, 0003, 20);INSERT 0 1 INSERT INTO ShopProduct VALUES(000C, 武侯區, 0004, 50);INSERT 0 1 INSERT INTO ShopProduct VALUES(000C, 武侯區, 0006, 90);INSERT 0 1 INSERT INTO ShopProduct VALUES(000C, 武侯區, 0007, 70);INSERT 0 1 INSERT INTO ShopProduct VALUES(000D, 錦江區, 0001, 100);INSERT 0 1 COMMIT;COMMIT

確認創建的表的內容:

SELECT * FROM ShopProduct;

執行結果:

shop_id | shop_name | product_id | quantity---------+-----------+------------+---------- 000A | 成華區 | 0001 | 30 000A | 成華區 | 0002 | 50 000A | 成華區 | 0003 | 15 000B | 金牛區 | 0002 | 30 000B | 金牛區 | 0003 | 120 000B | 金牛區 | 0004 | 20 000B | 金牛區 | 0006 | 10 000B | 金牛區 | 0007 | 40 000C | 武侯區 | 0003 | 20 000C | 武侯區 | 0004 | 50 000C | 武侯區 | 0006 | 90 000C | 武侯區 | 0007 | 70 000D | 錦江區 | 0001 | 100(13 行記錄)

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

--取得「在武侯區銷售的商品的銷售單價」 SELECT product_name, sale_price FROM Product WHERE product_id IN (SELECT product_id FROM ShopProduct WHERE shop_id = 000C);

執行結果:

product_name | sale_price--------------+------------ 運動T | 4000 菜刀 | 3000 叉子 | 500 擦菜板 | 880(4 行記錄)

如果在SELECT語句中使用了子查詢,那麼即使數據發生了變更,還可以繼續使用同樣的SELECT語句。像這樣能夠應對數據變更的程序,稱為『易維護程序』。

NOT IN 和子查詢

使用子查詢作為NOT IN 的參數:

SELECT product_name, sale_price FROM Product WHERE product_id NOT IN (SELECT product_id FROM ShopProduct WHERE shop_id = 000A);

執行結果:

product_name | sale_price--------------+------------ 菜刀 | 3000 高壓鍋 | 6800 叉子 | 500 擦菜板 | 880 圓珠筆 | 100(5 行記錄)

EXISTS謂詞

EXISTS謂詞的使用方法

一言以蔽之,謂詞的作用就是「判斷是否存在某種滿足條件的記錄」。如果存在這樣的記錄就返回真(TRUE),如果不存在這樣的記錄就返回假(FALSE)。EXISTS(存在)謂詞的主語是「記錄」。

--使用EXISTS選取出「武侯區在售商品的銷售單價」 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);

執行結果:

product_name | sale_price--------------+------------ 運動T | 4000 菜刀 | 3000 叉子 | 500 擦菜板 | 880(4 行記錄)

注釋:

  • 通常指定關聯子查詢作為EXISTS的參數。
  • 作為EXISTS參數的子查詢中通常使用SELECT *。

使用NOT EXISTS替換NOT IN

就像EXISTS可以替換IN一樣,NOT IN 也可以用NOT EXISTS 來替換。

--使用NOT EXISTS 讀取出「成華區店在售之外的商品的銷售單價」 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);

執行結果:

product_name | sale_price--------------+------------ 菜刀 | 3000 高壓鍋 | 6800 叉子 | 500 擦菜板 | 880 圓珠筆 | 100(5 行記錄)

CASE表達式

什麼是CASE表達式

CASE表達式是一種進行運算的功能,它是SQL中最重要的功能之一。CASE表達式是在區分情況下使用,這種情況的區分在編程中通常叫做條件(分支)。類似於C語言中的if……else….語句。

CASE表達式的語法

CASE表達式的語法分為簡單CASE表達式和搜索CASE表達式兩種。但是搜索CASE表達式包含了簡單CASE表達式的全部功能,所以我們學習搜索CASE表達式的語法就可以了。

--搜索CASE表達式CASE WHEN <求值表達式> THEN <表達式> WHEN <求值表達式> THEN <表達式> WHEN <求值表達式> THEN <表達式>..... ELSE <表達式>END

CASE表達式會從最初的WHEN子句中的「 <求值表達式> 」進行求值運算。所謂求值,就是要調查該表達式的真值是什麼,如果結果為真(TRUE),那麼就返回THEN子句中的表達式,CASE表達式的執行到此為止。如果結果不為真,那麼就跳轉到下一條的WHEN子句的求值之中。如果知道最後的WHEN子句為止返回結果都不為真,那麼就會返回ELSE中的表達式,執行結束。

CASE表達式的使用方法

咱們用一個例子說明:

--通過CASE表達式將A~C的字元串加入到商品種類中 SELECT product_name, CASE WHEN product_type = 衣服 THEN A: || product_type WHEN product_type = 辦公用品 THEN B: || product_type WHEN product_type = 廚房用具 THEN C: || product_type ELSE NULL END AS abs_product_type FROM Product;

執行結果:

product_name | abs_product_type--------------+------------------ T | A:衣服 打孔器 | B:辦公用品 運動T | A:衣服 菜刀 | C:廚房用具 高壓鍋 | C:廚房用具 叉子 | C:廚房用具 擦菜板 | C:廚房用具 圓珠筆 | B:辦公用品(8 行記錄)

注釋:

  • 雖然CASE表達式中的ELSE子句可以省略,但是最好不要省略。
  • CASE表達式中的END不能省略。

CASE表達式可以實現行列互換

使用GRUOP BY無法實現行列轉換:

SELECT product_type, SUM(sale_price) AS sum_price FROM Product GROUP BY product_type;

執行結果:

product_type | sum_price--------------+----------- 衣服 | 5000 辦公用品 | 600 廚房用具 | 11180(3 行記錄)

但是使用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;

執行結果:

sum_price_clothes | sum_price_kitchen | sum_price_office-------------------+-------------------+------------------ 5000 | 11180 | 600(1 行記錄)

今天的學習到此結束。加油!

每天學習一點點,每天進步一點點。

推薦閱讀:

1.7 操作系統管理硬體
6.暫停一段時間。
.net core下對於附件上傳下載的實現
學習SQL【2】-資料庫與SQL
這8個免費的網上課程可以有助你的技術成長

TAG:資料庫 | SQL | 自學編程 |