7、聯結表

1.關係表概述

背景: 假若有由同一供應商生產的多種物品,應當分爲多個表存儲:mysql

  • 由於同一供應商生產的每一個產品的供應商信息都是相同的,對每一個產品重複此信息既浪費時間又浪費存儲空間。
  • 若是供應商信息改變(例如,供應商搬家或電話號碼變更),只需改動一次便可。
  • 若是有重複數據(即每種產品都存儲供應商信息),很難保證每次輸入該數據的方式都相同。不一致的數據在報表中很難利用。

分爲兩個表存儲:sql

(1) product表存儲商品信息和供應商ID。關於供應商的信息除了ID外不在product表中存儲其它的。函數

(2) vendors 表包含全部供應商信息,每一個供應商佔一行,每一個供應商具備惟一的標識。此標識稱爲主鍵。在這裏是供應商ID。性能

如今咱們就能夠經過product表中的商品得到供應商ID, 而後再vendors表中找到供應商信息。學習

select vend_name,prod_name from vendors,products where vendors.vend_id = products.vend_id;

咱們經過一個where語句來聯結兩個表。這裏咱們的id都用徹底限定,即表名.列名,不然會出現二義性,不知道是哪一個表的字段。測試

where的重要性:
code

如上圖所述,咱們進行聯結的時候是將第一個表中的每一行與第二個表中的每一行配對。where進行過濾。blog

笛卡爾積:

由沒有聯結條件的表關係返回的結果爲笛卡兒積。檢索出的行的數目將是第一個表中的行數乘以第二個表中的行數。ip

上述基於兩個表之間的相等測試。這種聯結也稱爲==內部聯結==。產品

2. 內聯結。

select vend_name,prod_name,prod_price 
from vendors 
inner join products 
on vendors.vend_id = products.vend_id;

使用 inner join table_name on conditions來聯結table_name這個表,限制條件是conditions. 使用on來代替where子句。

也能夠聯結多個表:

select prod_name,vend_name,prod_price,quantity  
from orderitems,vendors,products 
where products.vend_id = vendors.vend_id 
and ordeeritems.prod_id = products.prod_id  
and order_num = 20005;

過濾出訂單編號爲20005的數據。

聯結的表越多,性能降低越厲害。

3. 自聯結。

首先說一下表別名

select cust_name , cust_contact 
from customers as c,orders as o,orderitems as oi where c.cust_id = o.cust_id 
and oi.order_num = o.order_.order_num 
and prod_id = 'TNT2';

如此更便捷。

tips:應該注意,表別名只在查詢執行中使用。與列別名不同,==表別名不返回到客戶機。==

使用自聯結的時候要用到表別名。例子:在一個商品表中,一個商品ID爲'DTNTR'的商品有問題,如今要找到它對應生產廠商所生產的全部商品。

咱們分兩步來檢索:

(1) 經過商品ID在表中檢索出廠家ID。

(2) 經過廠家ID檢索出全部這個廠家的商品。

若是使用子查詢是這樣的:

select prod_name,prod_id from products
where vend_id = 
(select vend_id from products 
where prod_id = 'DTNTR');

可是咱們能夠使用自聯結:

mysql> select p1.prod_name, p2.prod_id from products as p1, products as p2
-> where p1.prod_id = 'DTNTR' 
-> and p2.vend_id = p1.vend_id;

注意咱們使用的是p1.prod_name而不是prod_name。

4.外聯結

當咱們使用內聯結時,找到的都是等值匹配中存在的數據。若咱們要查找用戶的訂單數量,沒有訂單的也要顯示。

使用內聯結:

mysql> select customers.cust_id,orders.order_num
-> from customers inner join orders
-> on customers.cust_id = orders.cust_id;

輸出結果以下:

+---------+-----------+
| cust_id | order_num |
+---------+-----------+
|   10001 |     20005 |
|   10001 |     20009 |
|   10003 |     20006 |
|   10004 |     20007 |
|   10005 |     20008 |
+---------+-----------+
5 rows in set (0.00 sec)

很明顯咱們沒有把訂單數量爲空的cust_id找出來。

這個時候使用==外聯結:==

mysql> select customers.cust_id,orders.order_num
-> from customers left outer join orders
-> on customers.cust_id = orders.cust_id;

輸出以下:

+---------+-----------+
| cust_id | order_num |
+---------+-----------+
|   10001 |     20005 |
|   10001 |     20009 |
|   10002 |      NULL |
|   10003 |     20006 |
|   10004 |     20007 |
|   10005 |     20008 |
+---------+-----------+
6 rows in set (0.00 sec)

能夠看到咱們把order_num爲空的一塊兒檢索出來了。

如今學習一下外聯結的語法。

  • 關鍵字:OUTER JOIN. outer join來指定外聯結,外聯結不只包含有關係的行,還包括沒有關係的行。
  • 關鍵字:LEFT或者RIGHT. RIGHT 指出的是 OUTER JOIN 右邊的表,而 LEFT指出的是 OUTER JOIN 左邊的表。也就是從哪一個表檢索沒有關係的行。

5. 彙集函數和聯結表的結合使用

以cust_id爲分組,檢索customers和orders表中cust_id相同的數據(包括名字,id,和總數)。

mysql> select customers.cust_name,customers.cust_id,count(orders.order_num) as num_ord
-> from customers inner join orders
-> on customers.cust_id = orders.cust_id
-> group by customers.cust_id;

結果爲:

+----------------+---------+---------+
| cust_name      | cust_id | num_ord |
+----------------+---------+---------+
| Coyote Inc.    |   10001 |       2 |
| Wascals        |   10003 |       1 |
| Yosemite Place |   10004 |       1 |
| E Fudd         |   10005 |       1 |
+----------------+---------+---------+
4 rows in set (0.00 sec)

6. 注意點。

==應該老是提供聯結條件,不然會得出笛卡兒積。==

相關文章
相關標籤/搜索