用兩個表(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
說明:組合兩個表中的記錄,返回關聯字段相符的記錄,也就是返回兩個表的交集(陰影)部分。
2、左鏈接(左外鏈接)
3、右鏈接(右外鏈接)
4、全鏈接(全外鏈接)
5、補充,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
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
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 條件後將中止搜索更多行(在一個特定的組合鍵下)。