SQL (十二)創建高級聯結

在這裏插入圖片描述在這裏插入圖片描述

表的別名(AS關鍵字)

之前只用as給計算字段起過別名,由於有時候不區分計算字段和列,所以也可以說as可以用於給列起別名。總之,as可以給列和計算字段起別名,還可以給表起別名。

select concat(vend_name, '(', vend_country, ')') 
as vend_title
from vendors
order by vend_name;

在這裏插入圖片描述

計算字段必須用as起別名,因爲不起名字就是匿名的,沒法用。
但是給表起別名則是真的別名,可選的,不起人家也有名字。

select cust_name, cust_contact
from customers as C, orders as O, orderItems as OI
where prod_id = 'RGAN01'
AND OI.order_num = O.order_num
and C.cust_id = O.cust_id;

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

爲什麼給表起別名

在這裏插入圖片描述
一直覺得這種起別名的方式很類似C和C++的typedef關鍵字,所以作用當然也有類似的點:縮短代碼

在這裏插入圖片描述
很難理解,用一個例子來說明:

示例:在一條select語句多次引用一個表

太牛了

假設,我們要給和Jim Jones同一公司的所有顧客發郵件,那麼就要找出和Jim Jones同公司的所有顧客,假設我們只找名字,郵箱先不說。

那麼首先應該根據Jim Jones來找到Jim Jones工作的公司,然後再去找所有在這個公司工作的顧客。

使用子查詢

最內層的查詢:找到Jim Jones工作的公司

select cust_name
from Customers
where cust_contact = "Jim Jones";

在這裏插入圖片描述
結果是fun4all公司。

然後直接加上外層查詢,寫成嵌套的樣子:

select cust_id, cust_name, cust_contact
from Customers
where cust_name in (select cust_name
					from Customers
					where cust_contact = "Jim Jones");

在這裏插入圖片描述
於是就找到了Dennise這個顧客。

使用自聯結搭配表別名

select c1.cust_id, c1.cust_name, c1.cust_contact
from Customers as c1, Customers as c2 -- 牛不牛逼
where c2.cust_contact = "Jim Jones"
and c1.cust_name = c2.cust_name;

注意別名雖然在第二行才定義,但是第一行就在用了,因爲這是一個語句,分行只是格式而已。

第一個聯結條件用於過濾出c2表中所有聯繫人爲Jim Jones的行,其實就一行,即公司名cust_name爲fun4all的那行;

第二個條件再過濾出c1表中所有和c2表中過濾出的行的公司名相同的行,於是就得到這兩行結果。

注意最後顯示的是c1表的過濾結果,這個是重要的,因爲c2被過濾的只剩一行了
在這裏插入圖片描述
如果把第一行代碼改爲c2

select c2.cust_id, c2.cust_name, c2.cust_contact
from Customers as c1, Customers as c2 -- 牛不牛逼
where c2.cust_contact = "Jim Jones"
and c1.cust_name = c2.cust_name;

則顯示兩次jim的信息,因爲c2被過濾的只剩一行,卻又和c1匹配了2次
在這裏插入圖片描述
在這裏插入圖片描述

  • 很多DBMS處理聯結的速度比子查詢快得多。所以還是儘量用聯結。雖然不懂爲什麼會快得多,大概是底層代碼原因。
  • 用表別名引用的兩個表雖然是同一個表,但是DBMS卻把他們完全當做兩個表,這樣真的很方便。

和列別名的區別:不返回到客戶端;只在查詢時使用

在這裏插入圖片描述

其他聯結(除內聯結外)

在這裏插入圖片描述

自聯結 self join

見上一節的 示例:在一條select語句多次引用一個表

自然聯結 natural join:可能永遠也不會用到不是自然聯結的內聯結

在這裏插入圖片描述
在這裏插入圖片描述

由於沒出現過不是自然聯結的內聯結,所以並不清楚相同列多次出現是啥樣的

select C.*, O.order_num, O.order_date,
OI.prod_id, OI.quantity, OI.item_price
from Customers as C, Orders as O, OrderItems as OI
WHERE C.cust_id = O.cust_id
and OI.order_num  = O.order_num 
and prod_id = 'RGAN01';

可以看到select後面都是完全限定列名
在這裏插入圖片描述
在這裏插入圖片描述

外聯結 outer join

在這裏插入圖片描述

大概明白意思,因爲如果一個顧客沒有下訂單,他這行就不會關聯到orders表的某一行,於是聯結時就過濾不出來他這一行。

示例:左外聯結和右外聯結

假設要檢索出所有顧客,以及他們的訂單編號,使用內聯結寫代碼:

select Customers.cust_id, Orders.order_num
from Customers inner join Orders
on Customers.cust_id = Orders.cust_id;

在這裏插入圖片描述

  • 用了完全限定列名指明返回數據來自哪個表
  • inner join是用在from子句中的,把顧客表和訂單表聯結起來了
  • 聯結的條件用on子句寫

如果用外聯結寫:

select Customers.cust_id, Orders.order_num
from Customers left outer join Orders
on Customers.cust_id = Orders.cust_id;

在這裏插入圖片描述
在這裏插入圖片描述

  • left outer join,則要選擇顧客表的所有行,即沒在orders表的不滿足聯結條件的行也過濾出來。2號顧客沒下訂單,也被檢索出來了。
  • 如果用right,則訂單表的所有行都有,但是有訂單編號就一定有顧客編號,因爲下單了就已經是顧客了,所以這樣得到的結果和內聯結一樣。
select Customers.cust_id, Orders.order_num
from Customers right outer join Orders
on Customers.cust_id = Orders.cust_id;

在這裏插入圖片描述

  • 左外聯結和右外聯結可以互換,只要把表的順序換一下就好了
select Customers.cust_id, Orders.order_num
from Orders right outer join Customers
on Customers.cust_id = Orders.cust_id;

在這裏插入圖片描述
在這裏插入圖片描述

全外聯結(mysql不支持)

在這裏插入圖片描述
相當於左外聯結和右外聯結的結合版本了

select Customers.cust_id, Orders.order_num
from Orders full outer join Customers
on orders.cust_id = Customers.cust_id;

代碼報錯,因爲mysql不支持
在這裏插入圖片描述

帶聚集函數的聯結

之前學了5個聚集函數,count是其中之一

要和group by 一起用

內聯結

select Customers.cust_id,
	   count(Orders.order_num) as num_order
from Customers inner join Orders
on Customers.cust_id = Orders.cust_id
group by Customers.cust_id;

在這裏插入圖片描述
在這裏插入圖片描述
外左聯結

select Customers.cust_id,
	   count(Orders.order_num) as num_order
from Customers left outer join Orders
on Customers.cust_id = Orders.cust_id
group by Customers.cust_id;

在這裏插入圖片描述

使用聯結的注意要點

在這裏插入圖片描述

用聯結條件:

select cust_name, cust_contact
from customers as C, orders as O, orderItems as OI
where prod_id = 'RGAN01'
AND OI.order_num = O.order_num
and C.cust_id = O.cust_id;

在這裏插入圖片描述
不用聯結條件,返回笛卡爾積:

select cust_name, cust_contact
from customers as C, orders as O, orderItems as OI;

下圖不完整,但是能明白意思
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章