1. 程式人生 > >MySQL (3)表與表之間的聯絡 多表查詢

MySQL (3)表與表之間的聯絡 多表查詢

表與表之間的關係

(1)一對一:一對一關係就如球隊與球隊所在地址之間的關係,一支球隊僅有一個地址,而一個地址區也僅有一支球隊。這種情況需要找出主從關係,即誰是主表,誰是從表。有了球隊才有球隊地址區,所以球隊是主表,而球隊地址是從表。
一對一要求兩個表的主鍵必須完全一致,通過兩個表的主鍵建立關聯關係
這裡寫圖片描述

(2)一對多(多對一):最為常見的就是一對多!一對多和多對一,從球隊角度來說一個球隊擁有多個球員 即為一對多
多對一:從球員角度來說多個球員屬於一個球隊 即為多對一
資料表間一對多關係如下圖:
這裡寫圖片描述

(3)多對多:例如學生和選修課,即一個學生可以上多門課,而每門課也可以有多個學生。這種情況通常需要建立中間表來處理多對多關係。例如再建立一張 學生_選修課 表,給出兩個外來鍵,一個相對學生表的外來鍵,另一個相對課程表的外來鍵。
這裡寫圖片描述

多表查詢(重要)

多表查詢有如下幾種:
- 合併結果集;UNION 、 UNION ALL
- 連線查詢
這裡寫圖片描述
- 子查詢

【1】合併結果集
1.作用:合併結果集就是把兩個select語句的查詢結果合併到一起!
2.合併結果集有兩種方式:
(1)UNION:去除重複記錄,例如:SELECT * FROM t1 UNION SELECT * FROM t2;
(2)UNION ALL:不去除重複記錄,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
這裡寫圖片描述
這裡寫圖片描述
3.要求:被合併的兩個結果:列數、列型別必須相同。

【2】連線查詢 (非常重要)


連線查詢就是求出多個表的乘積,例如t1連線t2,那麼查詢出的結果就是t1*t2。
這裡寫圖片描述
連線查詢會產生笛卡爾積,假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以擴充套件到多個集合的情況。
那麼多表查詢產生這樣的結果並不是我們想要的,那麼怎麼去除重複的,不想要的記錄呢,當然是通過條件過濾。通常要查詢的多個表之間都存在關聯關係,那麼就通過關聯關係去除笛卡爾積。

你能想像到emp和dept表連線查詢的結果麼?emp一共14行記錄,dept表一共4行記錄,那麼連線後查詢出的結果是56行記錄。
也就你只是想在查詢emp表的同時,把每個員工的所在部門資訊顯示出來,那麼就需要使用主外來鍵來去除無用資訊了。
如下圖: 這裡我們要通過deptno來篩選出我們想要得到資訊
這裡寫圖片描述

使用主外來鍵關係做為條件來去除無用資訊

SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;
-- 在多表查詢中,在使用列時必須指定列所從屬的表,例如emp.deptno表示emp表的deptno列

上面查詢結果會把兩張表的 所有列都查詢出來,也許你不需要那麼多列,這時就可以指定要查詢的列了。

SELECT emp.ename,emp.sal,emp.COMM,dept.dname 
FROM emp,dept 
WHERE emp.deptno=dept.deptno;

還可以為表指定別名,然後在引用列時使用別名即可。

SELECT e.ename,e.sal,e.COMM,d.dname 
FROM emp AS e,dept AS d
WHERE e.deptno=d.deptno;[其中AS是可以省略的]

【3】內連線查詢
上面的查詢結果就是內連線查詢,但它不是SQL標準中的查詢方式。
內連線最大的特點就是隻返回兩個表中互相匹配的記錄,而那些不能匹配的記錄就被自動去除了
標準的內連線查詢為:

SELECT * 
FROM 表名1
INNER JOIN 表名2 
ON 連線規則;
INNER JOIN 表名3
ON 連線規則;
-- [不使用WHERE,而是使用ON]

如果將上面查詢emp和dept,使用內連線的方式就是:

SELECT * FROM emp e INNER JOIN dept d ON e.deptno=d.deptno;

可以輸出同樣的結果。

內連線分為 等值連線 ,自然連線 , 不等值連線 3種

等值連線就是連線規則用=號連線起來,如上

自然連線
大家也都知道,連線查詢會產生無用笛卡爾積,我們通常使用主外來鍵關係等式來去除它。而自然連線無需你去給出主外來鍵等式,它會自動找到這一等式:
兩張連線的表中名稱和型別完全一致的列作為條件,例如R表和S表都存在B列,並且型別一致,所以會被自然連線找到,然後將他們連線在一起
這裡寫圖片描述
這裡寫圖片描述

SELECT * FROM R NATURAL JOIN S

不等值連線
不等值連線就是連線規則由等號以外的運算子號組成,例如, < , >BETWEEN等
student表
這裡寫圖片描述
year表
這裡寫圖片描述

SELECT s.stuname,s.stuage,y.年齡大小 
FROM student AS s ,YEAR AS Y 
WHERE s.stuage BETWEEN y.起始年紀 AND y.終止年紀;

這裡寫圖片描述
將student表和year表連線起來,但是他們沒有共同的欄位,所以沒法用等值連線,通過使用不等值連線,規則是如果年齡在year表的起始年紀和終止年紀之間就可以連線。

【4】外連線查詢
在多表連線查詢時,有時希望所有記錄都被包含進去,即使沒有能匹配的記錄也被查詢結果集包含在內,這時,內連線就滿足不了需求了,這裡就要用到外連線查詢。
首先我們來看看student表
這裡寫圖片描述
score表
這裡寫圖片描述

我們來看看內連結查詢的結果

SELECT s.stuid,s.stuname,c.score FROM
student AS s INNER JOIN score AS c
ON s.stuid = c.stuid;

這裡寫圖片描述
可以看到因為score表中沒有王老五的stuid,所以它不在結果集。

這裡我們就可以用到外連線查詢
外連線查詢又分左外連線查詢,右外連結查詢。

左外連線查詢
左外連線查詢就是以左表為主,左側表的所有記錄都包含到結果集中,而右邊表中有匹配的記錄包含到結果集。

SELECT s.stuid,s.stuname,c.score FROM 
student AS s LEFT OUTER JOIN score AS c 
ON s.stuid = c.stuid;

這裡寫圖片描述

右外連線查詢
右外連線查詢就是以右表為主,右側表的所有記錄都包含到結果集中,而左邊表中有匹配的記錄包含到結果集。

SELECT s.stuid,s.stuname,c.score FROM 
student AS s RIGHT OUTER JOIN score AS c 
ON s.stuid = c.stuid;

這裡寫圖片描述

子查詢
一個select語句中包含另一個完整的select語句。
子查詢就是巢狀查詢,即SELECT中包含SELECT,如果一條語句中存在兩個,或兩個以上SELECT,那麼就是子查詢語句了。

子查詢出現的位置:
(1)where後,作為條為被查詢的一條件的一部分;
(2)from後,作表;

當子查詢出現在where後作為條件時,還可以使用如下關鍵字:
(1)any
(2)all 所有

子查詢結果集的形式:
(1)單行單列(用於條件)
(2)單行多列(用於條件)
(3)多行單列(用於條件)
(4)多行多列(用於表)

練習:

(1)工資高於JONES的員工。
分析:
查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。

第一步:查詢JONES的工資

SELECT sal FROM emp WHERE ename='JONES'

第二步:查詢高於甘寧工資的員工

SELECT * FROM emp WHERE sal > (${第一步});

結果

SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES');

(2)查詢與SCOTT同一個部門的員工。
第一步:查詢出SCOTT的部門編號

SELECT deptno FROM emp WHERE ename = 'SCOTT'

第二部:查詢出 該部門編號的員工

SECECT * FROM emp WHERE deptno =(${第一步});

結果

SELECT * FRMO emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SCOTT');

子查詢作為條件:子查詢形式為單行單列

(3)工資高於30號部門所有人的員工資訊
分析:
SELECT * FROM emp WHERE sal>(
SELECT MAX(sal) FROM emp WHERE deptno=30);

查詢條件:工資高於30部門所有人工資,其中30部門所有人工資是子查詢。高於所有需要使用all關鍵字。

第一步:查詢30部門所有人工資

SELECT sal FROM emp WHERE deptno=30;

第二步:查詢高於30部門所有人工資的員

SELECT * FROM emp WHERE sal > ALL (${第一步})

結果

SELECT * FROM emp WHERE sal > ALL(SELECT sal FROM emp WHERE deptno=30)

子查詢作為條件:子查詢形式為多行單列(當子查詢結果集形式為多行單列時可以使用ALL或ANY關鍵字)