今天要來介紹SQL語法中的集合運算。比較可惜的是今天介紹的三種集合指令只有一種在mysql可以直接被使用,其餘的兩種指令都必須要透過改寫才有辦法直接操作,這個部分我們點到而已不會仔細的討論,所以今天的篇幅會稍短一些。
首先我們要介紹的是集合運算的概念,讓我們看一下下面從網路上擷取的這張圖。
如果我們說左邊是A集合右邊是B集合那 A 聯集 (Union) B 就是兩者共同擁有的元素。
A = { X, Y }, B = { Y, Z, K }, A ⋃ B = { X, Y, Z, K }
這裡很重要的一件事情是會發現即使 A 集合中出現過Y,B 集合中也出現過 Y,但是聯集之後的結果中 Y 只會出現一次。
另外兩種集合運算一個叫做差集 (Difference)
另外一個叫做交集 (Intersection)。
差集指的是兩個集合之間不同的元素,相對的交集指的是兩個集合相同的元素。祝你想要講最重要的一件事情是幾何運算結果中的元素都只會出現一次。為什麼這件事情這麼重要呢?因為在SQL的運算執行過程當中所有的運算都不是使用集合運算。正也是為什麼我們在第四天的SQL教學中會使用distinct這一個關鍵字來過濾重複出現的結果。今天就讓我們來看看如何在SQL中使用集合運算。
首先讓我們假定下面的這一個查詢,今天我們想要查找的是在我們的菜單裡面價格小於30元、或是價格大於50元、又或者是在顧客評分大於3分的商品編號 (MenuID)。用傳統的SQL思考邏輯,首先我們會需要 Menu 這個關係表以及 Review 的關係。表接下來我們使用在第五天的鏈結 (Join) 將兩個關係表串起來,然後透過上述的條件做篩選,寫成下面這個SQL:
Select menu.MenuID
from menu Left Outer Join review
On menu.menuID = review.menuID
where price <= 30 or price > 50 or rating > 3;
這邊我使用的鏈結方式是用left outer join,理由是因為在Menu的關係表中,有一些沒有出現在review的關係表中的資料。另外我在上面的結果偷偷幫大家把原本選取的MenuID改成星號,這樣會比較知道兩個關聯表在戀姐和選過後剩餘的項目,因為在review的關係表中,有重複出現的評分,所以會發現鏈結兩張表之後,最後的結果就會像左邊那樣,MenuID 重複出現。當然為了要避免重複出現的結果我們也可以在最上面 Select 的部分使用 Distinct 當重複的資料只出現一次。
SQL在預設的計算中使用一個我們稱之為bed Operation的操作模式。這個操作模式會把每一組出現的資料及再結合或是三去的時候一到他的個數作累計,更白話的是該重複的數值就一定會重複。
上面同樣一個問題如果我們想使用集合運算該怎麼寫呢?我們可以把同樣的問題想像成先在Menu關係表中對所有的品項在價格的部分做篩選,結者我們在review的關係表中對所有的評分做篩選,最後把兩個篩選出來的結果用聯集串起來。寫出來就像這樣:
(Select menuID
From menu
where price <= 30 or price > 50)
Union
(Select menuID
from review
where rating > 3);
只要是 Set Operation的指令,都是在關鍵字的上下兩端使用子查詢,將結果串接。這樣子的指令要注意的事情是兩個子查詢的結果必須要是同樣的一個資料屬性。也就是在這一個上述的SQL指令中會發現兩個子查詢回傳的都是人MenuID。如果我剛剛兩個子查詢都使用星號,MySQL 就會抱怨兩個回傳的資料集合不能合併!
今天沒有講到的兩個集合運算一個是 Intersect: 負責的就是做交集。有一些SQL語法中其實是有支援 Intersect 的:
Subquery
Intersect
Subquery;
這樣的語法就會回傳兩個子查詢結果中相同的資料。
另一個是Except,其實在 SQL中可以透過 NOT IN (昨天有介紹!) 來達成一樣的結果。將第一個子查詢去除第二個子查詢的結果。
Subquery
Except
Subquery
為了讓資料多元一點,明天我們要來介紹怎麼創建資料庫、管理資料!
--
圖片取自 Wikipedia 集合(數學)