圖解MySQL 內鏈接、外鏈接、左鏈接、右鏈接、全鏈接……太多了

圖解MySQL 內鏈接、外鏈接、左鏈接、右鏈接、全鏈接……太多了

 

用兩個表(a_table、b_table),關聯字段a_table.a_id和b_table.b_id來演示一下MySQL的內鏈接、外鏈接( 左(外)鏈接、右(外)鏈接、全(外)鏈接)。php

MySQL版本:Server version: 5.6.31 MySQL Community Server (GPL)html

數據庫表:a_table、b_tablemysql

主題:內鏈接、左鏈接(左外鏈接)、右鏈接(右外鏈接)、全鏈接(全外鏈接)sql

前提

建表語句:

CREATE TABLE `a_table` ( `a_id` int(11) DEFAULT NULL, `a_name` varchar(10) DEFAULT NULL, `a_part` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8

 

CREATE TABLE `b_table` ( `b_id` int(11) DEFAULT NULL, `b_name` varchar(10) DEFAULT NULL, `b_part` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8

表測試數據:


1、內鏈接

關鍵字:inner join on
語句:select * from a_table a inner join b_table bon a.a_id = b.b_id;
執行結果:

說明:組合兩個表中的記錄,返回關聯字段相符的記錄,也就是返回兩個表的交集(陰影)部分。

2、左鏈接(左外鏈接)

關鍵字:left join on / left outer join on
語句:select * from a_table a left join b_table bon a.a_id = b.b_id;
執行結果:
 
說明:
left join 是left outer join的簡寫,它的全稱是左外鏈接,是外鏈接中的一種。
左(外)鏈接,左表(a_table)的記錄將會所有表示出來,而右表(b_table)只會顯示符合搜索條件的記錄。右表記錄不足的地方均爲NULL。

3、右鏈接(右外鏈接)

關鍵字:right join on / right outer join on
語句:select * from a_table a right outer join b_table b on a.a_id = b.b_id;
執行結果:

說明:
right join是right outer join的簡寫,它的全稱是右外鏈接,是外鏈接中的一種。
與左(外)鏈接相反,右(外)鏈接,左表(a_table)只會顯示符合搜索條件的記錄,而右表(b_table)的記錄將會所有表示出來。左表記錄不足的地方均爲NULL。


4、全鏈接(全外鏈接)

MySQL目前不支持此種方式,能夠用其餘方式替代解決。

5、補充,MySQL如何執行關聯查詢

MySQL認爲任何一個查詢都是一次「關聯」,並不只僅是一個查詢須要到兩個表匹配才叫關聯,因此在MySQL中,每個查詢,每個片斷(包括子查詢,甚至基於單表查詢)均可以是一次關聯。
當前MySQL關聯執行的策略很簡單:MySQL對任何關聯都執行嵌套循環關聯操做,即MySQL先在一個表中循環取出單條數據,而後在嵌套循環到下一個表中尋找匹配的行,依次下去,直到找到全部表中匹配的行爲止。而後根據各個表匹配的行,返回查詢中須要的各個列。請看下面的例子中的簡單的查詢:
 
查詢語句:select tbl1.col1, tbl2.col2 from tbl1 inner join tbl2 using(col3) where tbl1.col1 in (5, 6);
假設MySQL按照查詢中的表順序進行關聯操做,咱們則能夠用下面的僞代碼表示MySQL將如何完成這個查詢:
outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end outer_row = outer_iter.next end

 

上面的執行計劃對於單表查詢和多表關聯查詢都適用,若是是一個單表查詢,那麼只須要上面外層的基本操做。對於外鏈接,上面的執行過程仍然適用。例如,咱們將上面的查詢語句修改以下:
select tbl1.col1, tbl2.col2 from tbl1 left outer join tbl2 using(col3) where tbl1.col1 in (5, 6);
那麼,對應的僞代碼以下:
outer_iter = iterator over tbl1 where col1 in (5, 6) outer_row = outer_iter.next while outer_row inner_iter = iterator over tbl2 where col3 = outer_row.col3 inner_row = inner_iter.next if inner_row while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end else output [ outer_row.col1, null] end outer_row = outer_iter.next end

 

說明:第五部分摘自《高性能MySQL 第三版》
 

數據庫之聯合查詢和鏈接查詢

1.JOIN和UNION區別
join 是兩張表作交連后里麪條件相同的部分記錄產生一個記錄集,
union是產生的兩個記錄集(字段要同樣的)並在一塊兒,成爲一個新的記錄集。

JOIN用於按照ON條件聯接兩個表,主要有四種:
INNER JOIN:內部聯接兩個表中的記錄,僅當至少有一個同屬於兩表的行符合聯接條件時,內聯接才返回行。我理解的是隻要記錄不符合ON條件,就不會顯示在結果集內。
LEFT JOIN / LEFT OUTER JOIN:外部聯接兩個表中的記錄,幷包含左表中的所有記錄。若是左表的某記錄在右表中沒有匹配記錄,則在相關聯的結果集中右表的全部選擇列表列均爲空值。理解爲即便不符合ON條件,左表中的記錄也所有顯示出來,且結果集中該類記錄的右表字段爲空值。
RIGHT JOIN / RIGHT OUTER JOIN:外部聯接兩個表中的記錄,幷包含右表中的所有記錄。簡單說就是和LEFTJOIN反過來。
FULL JOIN / FULL OUTER JOIN:完整外部聯接返回左表和右表中的全部行。就是LEFTJOIN和RIGHTJOIN和合並,左右兩表的數據都所有顯示。數據庫

JOIN的基本語法:
Select table1.* FROM table1 JOIN table2 ON table1.id=table2.idmarkdown

sql寫法
內鏈接innerjoin:
SELECT msp.name, party.name
FROM msp JOIN party ON party=code

SELECT msp.name, party.name
FROM msp inner JOIN party ON party=code

左鏈接leftjoin :
SELECT msp.name, party.name
FROM msp LEFT JOIN party ON party=code

右鏈接rightjoin :
SELECT msp.name, party.name
FROM msp RIGHT JOIN party ON msp.party=party.codepost

全鏈接(fulljoin):
SELECT msp.name, party.name
FROM msp FULL JOIN party ON msp.party=party.code性能

 

UNION運算符
將兩個或更多查詢的結果集組合爲單個結果集,該結果集包含聯合查詢中的全部查詢的所有行。UNION的結果集列名與UNION運算符中第一個Select語句的結果集的列名相同。另外一個Select語句的結果集列名將被忽略。
其中兩種不一樣的用法是UNION和UNIONALL,區別在於UNION從結果集中刪除重複的行。若是使用UNIONALL 將包含全部行而且將不刪除重複的行。測試

UNION和UNIONALL的區別:
union 檢查重複
union all 不作檢查
好比select 'a' union select 'a' 輸出就是一行 a
好比select 'a' union all select 'a' 輸出就是兩行 aatom

2.經過下面的例子,能夠清晰的看出和理解2者的區別
實例1典型的二錶鏈接演示

假定有兩個表Table1和Table2,其包含的列和數據分別如表1.1和表1.2所示。

表1.1Table1數據庫

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

 

表1.2Table2數據庫表

 

ColumnA

ColumnD

ColumnE

X1

D1

E1

X2

D2

E2

X3

D3

E3

 

Table1和Table2表共有的列爲ColumnA,若是經過ColumnA列的值鏈接Table1和Table2兩個表,即鏈接條件爲Table1.ColumnA=Table2.ColumnA,此時獲得的鏈接結果如表1.3所示。

表1.3 鏈接Table1和Table2表

ColumnA

ColumnB

ColumnC

ColumnD

ColumnE

X1

Y1

Z1

D1

E1

X2

Y2

Z2

D2

E2

X3

Y3

Z3

D3

E3

上述鏈接過程的實現代碼可表示以下:SELECT* FROM Table1 JOIN Table2 ON Table1.ColumnA=Table2.columnA

實例2 典型的二表記錄的UNION運算

假定有兩個表Table3和Table4,其包含的列和數據分別如表2.1和表2.2所示。

表2.1Table3數據庫表

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

 

表2.2Table4數據庫表、

 

ColumnA

ColumnD

ColumnE

X4

Y4

Z4

X5

Y5

Z5

X6

Y6

Z6

 

Table3表和Table4表具備相同的列結構,列數也要相同,列名能夠不一樣,以第一個表的列名爲新表的列名,所以可使用UNION運算符鏈接兩個表的記錄集,獲得的鏈接結果如表2.3所示。

表2.3 使用UNION鏈接Table3表和Table4表的記錄

 

ColumnA

ColumnB

ColumnC

X1

Y1

Z1

X2

Y2

Z2

X3

Y3

Z3

X4

Y4

Z4

X5

Y5

Z5

X6

Y6

Z6

上述鏈接過程的實現代碼可表示以下:SELECT * FROM Table3 UNION SELECT *FROMTable4

 

SQL語法——left join on 多條件

 

left join on +多條件與where區別

重點

先匹配,再篩選where條件。


本文將經過幾個例子說明二者的差異。

表1:product

id amount
1 100
2 200
3 300
4 400

表2:product_details

id weight exist
2 22 0
4 44 1
5 55 0
6 66 1

1. 單個條件

select * from product a
left join  product_details b
on a.id  = b.id

以左表爲準匹配,結果:

id amount id weight exist
1 100 null null null
2 200 2 22 0
3 300 null null null
4 400 4 44 1

2. 條件寫在on 與where區別

查詢1:

SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
AND   product.amount=200;

結果:

id amount id weight exist
1 100 null null null
2 200 2 22 0
3 300 null null null
4 400 null null null

把on的全部條件做爲匹配條件,不符合的右表都爲null。
查詢2:

SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
WHERE product.amount=200;

 

id amount id weight exist
2 200 2 22 0

匹配完再篩選,結果只有一條記錄。

3. where XXX is null 狀況

使用該語句表示:刪除掉不匹配on後面條件的記錄。
where XXX is not null 則表示篩選出符合on後面條件的記錄。
經常使用於只須要左表的數據,好比count id這類。

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id AND b.weight!=44 AND b.exist=0
WHERE b.id IS NULL;

結果:

id amount
1 100
3 300
4 400

能夠直觀看出,只有id=2的紀錄徹底匹配上三個條件,因此篩除這條紀錄,另三條保留,此時這三條紀錄的右表均爲null。
篩選出不符合on後面條件的,即 !(a.id=b.id AND b.weight!=44 AND b.exist=0).
!(a.id=b.id AND || !(b.weight!=44) || !(b.exist=0).
(a.id != b.id AND || (b.weight = 44) || ( b.exist! = 0).
邏輯 AND 和 邏輯 OR表達式,其操做數是從左到右求值的。若是第一個參數作夠判斷操做結果,那麼第二個參數便不會被計算求值(短路效果)。

下面語句與該語句效果相同:(這裏相同指的是最後只用到左表數據,如果將右表數據寫出來是不同的)

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id
WHERE b.id is null OR b.weight=44 OR b.exist=1;

 

將on的否認條件寫在where後,效果相同。

注:
若是你使用 LEFT JOIN 來尋找在一些表中不存在的記錄,你須要作下面的測試:WHERE 部分的 col_name IS NULL,MYSQL 在查詢到一條匹配 LEFT JOIN 條件後將中止搜索更多行(在一個特定的組合鍵下)。

參考:https://blog.csdn.net/czhphp/article/details/18657341

相關文章
相關標籤/搜索