MySql:多表查詢

上一篇博客介紹了多表設計,那麼既然有了多表設計很自然就有多表查詢啦~
首先簡單說一下數學中的笛卡爾積~
在數學中,兩個集合XY笛卡兒積(Cartesian product),又稱直積,表示爲X × Y,第一個對象是X的成員而第二個對象是Y的所有可能有序對的其中一個成員
假設集合A={a, b},集合B={0, 1, 2},則兩個集合的笛卡爾積爲{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。

相信短短兩行文字就足以令廣大程序員大概明白什麼叫做笛卡爾積。
那麼跟多表查詢有什麼關係呢?

在查詢中有一種叫做笛卡爾積查詢
還是繼續上篇的例子~感興趣的盤友可以看看上一篇:
上篇中的兩個表:dept與emp,其中emp中的字段dept_id作爲外鍵關聯着dept的id~那麼如果我有這樣的需求:查詢員工的同時查詢他們的部門~
這很明顯就是跨表數據查詢~那麼怎麼查呢~我們先說一下上面提到的笛卡爾積查詢:
select *from dept,emp;
+----+--------+----+------+---------+--------+
| id | name   | id | name | dept_id | salary |
+----+--------+----+------+---------+--------+
|  1 | 人事部 |  1 | 曹操 |       1 |   2000 |
|  1 | 人事部 |  2 | 荀彧 |       2 |   2000 |
|  1 | 人事部 |  4 | 郭嘉 |       4 |   2000 |
|  2 | 後勤部 |  1 | 曹操 |       1 |   2000 |
|  2 | 後勤部 |  2 | 荀彧 |       2 |   2000 |
|  2 | 後勤部 |  4 | 郭嘉 |       4 |   2000 |
|  3 | 財務部 |  1 | 曹操 |       1 |   2000 |
|  3 | 財務部 |  2 | 荀彧 |       2 |   2000 |
|  3 | 財務部 |  4 | 郭嘉 |       4 |   2000 |
|  4 | 行政部 |  1 | 曹操 |       1 |   2000 |
|  4 | 行政部 |  2 | 荀彧 |       2 |   2000 |
|  4 | 行政部 |  4 | 郭嘉 |       4 |   2000 |
+----+--------+----+------+---------+--------+

可以看到查詢結果跟文章開頭所介紹的概念一樣:
A={a, b},集合B={0, 1, 2},則兩個集合的笛卡爾積爲{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。

不過所查詢出來的結果明顯是不對的,那筆者爲什麼要提到笛卡爾積呢?
那是因爲多表查詢是基於笛卡爾積查詢的。

連接查詢:
基於笛卡爾積查詢的結果進行過濾就可以得到正確的查詢結果,那麼過濾的條件很明顯就是dept_id與dept的id相等了。
select *from dept,emp where dept.id=emp.dept_id;
+----+--------+----+------+---------+--------+
| id | name   | id | name | dept_id | salary |
+----+--------+----+------+---------+--------+
|  1 | 人事部 |  1 | 曹操 |       1 |   2000 |
|  2 | 後勤部 |  2 | 荀彧 |       2 |   2000 |
|  4 | 行政部 |  4 | 郭嘉 |       4 |   2000 |
+----+--------+----+------+---------+--------+
這樣就可以正確查出結果了,我們稱這種查詢叫做內連接查詢,內連接查詢的是兩個表都能找到對應記錄的記錄。

內連接查詢還有另外一種查詢方法:
同樣是基於上面的需求,
select * from dept inner join emp on dept.id=emp.dept_id;
+----+--------+----+------+---------+--------+
| id | name   | id | name | dept_id | salary |
+----+--------+----+------+---------+--------+
|  1 | 人事部 |  1 | 曹操 |       1 |   2000 |
|  2 | 後勤部 |  2 | 荀彧 |       2 |   2000 |
|  4 | 行政部 |  4 | 郭嘉 |       4 |   2000 |
+----+--------+----+------+---------+--------+
可以看到所查詢出來的結果是一致的。

左外連接查詢:
筆者一開始給dept插入的數據有四條,分別是人事部,後勤部,科技部,行政部。但是從上面的查詢結果來看,可以看到是少了科技部。
爲什麼會少了科技部呢?因爲emp表中沒有人是屬於科技部的,而上面提到內連接所查詢的是兩個表都能找到對應記錄的記錄。所以科技部沒有顯示出來。但是你不顯示出來別人還以爲沒有這個部門呢?假如就算沒有員工也要顯示出來,那麼該怎麼查呢?看下面查詢語句:
select * from dept left join emp on dept.id=emp.dept_id;
+----+--------+------+------+---------+--------+
| id | name   | id   | name | dept_id | salary |
+----+--------+------+------+---------+--------+
|  1 | 人事部 |    1 | 曹操 |       1 |   2000 |
|  2 | 後勤部 |    2 | 荀彧 |       2 |   2000 |
|  4 | 行政部 |    4 | 郭嘉 |       4 |   2000 |
|  3 | 財務部 | NULL | NULL |    NULL |   NULL |
+----+--------+------+------+---------+--------+

這樣就可以了。這種查詢叫做左外連接查詢,左外連接查詢是基於內鏈接查詢的。在內鏈接查詢的結果上增加左邊表有而右邊表沒有的記錄。這裏所指的左邊表是指寫查詢語句的時候寫的第一個表,例如:select * from dept left join emp on dept.id=emp.dept_id;
其中dept就在左邊,emp就在右邊,所以dept就是左邊的表,emp就是右邊的表。


右外連接查詢:
既然有左外連接查詢那麼就有右外連接查詢,所謂的右外連接查詢跟左外連接查詢差不多,右外連接查詢同樣是基於內鏈接查詢的。在內鏈接查詢的結果上增加右邊表有而左邊表沒有的記錄。
select * from dept right  join emp on dept.id=emp.dept_id;
所謂的左和右不過是相對的,就在於查詢的時候先寫哪個表。這裏就不再演示了。


全外連接查詢:
在演示這種查詢之前,筆者先插入一條記錄到emp表:
insert into emp values (null,'荀攸',null,2000);
這個時候emp表裏面的記錄是這樣的:
+----+------+---------+--------+
| id | name | dept_id | salary |
+----+------+---------+--------+
|  1 | 曹操 |       1 |   2000 |
|  2 | 荀彧 |       2 |   2000 |
|  4 | 郭嘉 |       4 |   2000 |
|  5 | 荀攸 |    NULL |   2000 |
+----+------+---------+--------+
現在emp表有dept表沒有對應的內容,而dept表也有emp表沒有對應的內容。
那麼如果我想查詢的是:在內連接查詢的結果上加上右邊表有而左邊表沒有的記錄再加上左邊表有而右邊表沒有的記錄呢?
那麼這個時候我們就要用全外連接查詢了,我們來看一下怎麼使用這種查詢:
select * from dept full  join emp on dept.id=emp.dept_id;
..........把這條命令敲上去之後發現報錯了~~爲什麼會報錯呢?那是因爲mysql不支持全外連接查詢~呵呵這不是坑爹嗎?沒錯就是坑爹~
想要報復嗎?快在文章末尾評論一下隨便稱讚幾句當做對筆者的報答~不對!報復纔是!

那麼是不是就不能全外連接查詢了呢?全外連接查詢無非就是左外連接查詢與右外連接查詢的結合~那麼我們接下來使用一個union給兩句查詢語句合併使用。
select * from dept left join emp on dept.id=emp.dept_id
union
select * from dept right join emp on dept.id=emp.dept_id;

+------+--------+------+------+---------+--------+
| id   | name   | id   | name | dept_id | salary |
+------+--------+------+------+---------+--------+
|    1 | 人事部 |    1 | 曹操 |       1 |   2000 |
|    2 | 後勤部 |    2 | 荀彧 |       2 |   2000 |
|    4 | 行政部 |    4 | 郭嘉 |       4 |   2000 |
|    3 | 財務部 | NULL | NULL |    NULL |   NULL |
| NULL | NULL   |    5 | 荀攸 |    NULL |   2000 |
+------+--------+------+------+---------+--------+

好~“拼湊版全外連接查詢”大功告成!









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