1. 程式人生 > >MYSQL的各種連線(Inner join,outer join,left join,right join)

MYSQL的各種連線(Inner join,outer join,left join,right join)

H. cross join

表A和表B的資料進行一個N*M的組合,即笛卡爾積(交差集)。一般來說,我們很少用到這個語法。因為這種集合的使用對於效能來說非常危險,尤其是表很大。這裡就不做介紹了…

例外的例子:

一.先看一些最簡單的例子

例子

Table A
aid   adate 
1      a1 
2      a2 
3      a3

TableB

bid bdate 
1    b1 
2    b2 
4    b4 
兩個表a,b相連線,要取出id相同的欄位 
select * from a inner join b on a.aid = b.bid這是僅取出匹配的資料. 
此時的取出的是: 
1 a1 b1 
2 a2 b2 

那麼left join 指: 
select * from a left join

 b on a.aid = b.bid 
首先取出a表中所有資料,然後再加上與a,b匹配的的資料 
此時的取出的是: 
1 a1 b1 
2 a2 b2 
3 a3 空字元 

同樣的也有right join 
指的是首先取出b表中所有資料,然後再加上與a,b匹配的的資料 
此時的取出的是: 
1 a1 b1 
2 a2 b2 
4 空字元 b4

LEFT JOIN 或 LEFT OUTER JOIN。 
左向外聯接的結果集包括 LEFT OUTER 子句中指定的左表的所有行,而不僅僅是聯接列所匹配的行。如果左表的某行在右表中沒有匹配行,則在相關聯的結果集行中右表的所有選擇列表列均為空值

二. left join/right join/inner join操作演示

表A記錄如下:
aID        aNum
1           a20050111
2           a20050112
3           a20050113
4           a20050114
5           a20050115


表B記錄如下:
bID        bName
1            2006032401
2           2006032402
3           2006032403
4           2006032404
8           2006032408

實驗如下:
1.    left join
sql語句如下: 
SELECT*FROM A
LEFTJOIN B 
ON A.aID = B.bID
結果如下:

aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404
5            a20050115         NULL       NULL

(所影響的行數為 5 行)

結果說明:
        left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為準的.
換句話說,左表(A)的記錄將會全部表示出來,而右表(B)只會顯示符合搜尋條件的記錄(例子中為: A.aID = B.bID).
B表記錄不足的地方均為NULL.


2.    right join
sql語句如下: 
SELECT*FROM A
RIGHTJOIN B 
ON A.aID = B.bID
結果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404
NULL    NULL                8              2006032408

(所影響的行數為 5 行)

結果說明:
        仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充.


3.inner join
sql語句如下: 
SELECT*FROM A
INNERJOIN B 
ON A.aID = B.bID
結果如下:
aID        aNum                   bID           bName
1            a20050111         1               2006032401
2            a20050112         2              2006032402
3            a20050113         3              2006032403
4            a20050114         4              2006032404


結果說明:
        很明顯,這裡只顯示出了 A.aID = B.bID的記錄.這說明inner join並不以誰為基礎,它只顯示符合條件的記錄.


-----------------[以下為網上的一點資料]------------------ 
LEFT JOIN操作用於在任何的 FROM 子句中,組合來源表的記錄。使用 LEFT JOIN 運算來建立一個左邊外部聯接。左邊外部聯接將包含了從第一個(左邊)開始的兩個表中的全部記錄,即使在第二個(右邊)表中並沒有相符值的記錄。 

語法:
FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2 

說明:
① table1, table2引數用於指定要將記錄組合的表的名稱。
② field1, field2引數指定被聯接的欄位的名稱。且這些欄位必須有相同的資料型別及包含相同型別的資料,但它們不需要有相同的名稱。
③ compopr引數指定關係比較運算子:"=", "<", ">", "<=", ">=" 或 "<>"。
④ 如果在INNER JOIN操作中要聯接包含Memo 資料型別或 OLE Object 資料型別資料的欄位,將會發生錯誤。

三.相關的複雜的解釋和例項

簡介: 外部連線和自聯接 inner join(等值連線) 只返回兩個表中聯結欄位相等的行 left join(左聯接) 返回包括左表中的所有記錄和右表中聯結欄位相等的記錄 right join(右聯接) 返回包括右表中的所有記錄和左表中聯結欄位相等的記錄 on 指定表間聯結欄位及其關係的等號 "=" 表示式, 返回 true 或 false. 當表示式返回 true 時, 則查詢中包含該記錄. ! 外部連線只能操作已存在於資料庫中的資料
update (ctarticle as a left join ctclass as c on a.classid = c.classid) left join cttag as b on a.articleid = b.articleid 
set tag=tag+' ', b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid 
where a.classid=23 and a.nclassid=0 and tagid is not null 

update (ctarticle as a left join (ctnclass as c left join ctclass as d on c.classid = d.classid) on a.nclassid = c.nclassid and a.classid = c.classid) left join cttag as b on a.articleid = b.articleid set tag=d.class+' '+c.nclass, b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid where a.classid=23 and a.nclassid=197; 

更新操作 
左連線中資料的篩選 
insert into cttag(articleid,classid,nclassid) select a.articleid,a.classid,a.nclassid from ctarticle a left join cttag b on a.articleid=b.articleid where b.articleid is null 

//本語句功能為, 顯示主表的全部內容, 插入資料到副表中沒有的資料 
//主要作用為: 讓資料減少冗餘 

上例中的延續 
select a.*, b.*, c.*, d.* from cttag as d left join ((ctarticle as a left join ctclass as b on a.classid=b.classid) left join ctnclass as c on a.nclassid=c.nclassid) on d.articleid=a.articleid; 

顯示文章表中的全部, 呼叫類別表中的欄目 
select a.*, b.*, c.* from (ctarticle a left join ctclass b on a.classid=b.classid) left join ctnclass c on a.nclassid=c.nclassid 

//作用, 有時在文章表中包含了在個別類別表中沒有的資料, 用這個語法可以讀出文章表的全部資料 
//a 為 文章表, b 為主類別, c 為子類別 

同上例, 選擇追加資料時加上空格 
insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+' '+c.nclass 
from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=4 and a.nclassid=154; 

連線n個表, 並追加資料到其中一個表, n=4 
insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+c.nclass 
from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1; 

//解讀 
插入到 表2(欄1,欄2,欄3,欄4) 
選擇 別名a.欄1, 別名a.欄2, 別名a.欄3, 別名d.欄4 加上 別名c.欄5 
從 (表1 別名a 左連線 (表3 別名c 左連線 表4 別名d 在 別名c.欄2 等於 別名d.欄2) 在 別名a.欄2 等於 別名c.欄2 和 別名a.欄3=別名c.欄3) 左連線 表2 別名b 在 別名a.欄1 等於 別名b.欄1 在那裡 別名a.欄2=1 和 別名a.欄3=1 

連線兩個表, 並追加資料到其中一個表 
insert into cttag(articleid,classid,nclassid) 
select a.articleid,a.classid,a.nclassid 
from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1; 

//解讀 
插入到 表2(欄1,欄2,欄3) 
選擇 別名a.欄1, 別名a.欄2, 別名a.欄3 
從 表1 別名a 左連線 表2 別名b 在 別名a.欄1 等於 別名b.欄1 在那裡 別名a.欄4=1 和 別名a.欄5=1 

左連線 

同步兩表的資料 
update ctarticle a inner join cttag b on a.articleid = b.articleid set b.classid=a.classid, b.nclassid=a.nclassid; 

//解讀 
更新 表1 別名a 聯接 表2 別名2 在 別名a.欄1 等於 別名b.欄1 設定 別名b.欄2 更新為 別名a.欄2, 別名b.欄3 更新為 別名a.欄3 

右外連線 
select a.*, b.* from bunclass a right join ctclass b on a.classid=b.classid where a.nclassid=20 

查詢別名 a,b 表, 只匹配 b 表中的內容. 

新增資料到連線表之一 
insert into cttag ( tag, articleid ) select top 1 b.tag, a.articleid from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.articleid order by a.articleid desc; 

變通中的用法二 
insert into bureply 
select b.*, a.classid, a.nclassid 
from article as a inner join reply as b on a.articleid = b.articleid 
where classid=50; 

實際應用中的變通 
insert into butag ( tag, articleid, classid, nclassid) 
select b.tag, a.articleid, a.classid, a.nclassid 
from article as a inner join tag as b on a.articleid = b.articleid 
where classid=24; 


新增資料到其他表 
insert into butag ( tag, articleid ) 
select b.tag, a.articleid 
from article as a inner join tag as b on a.articleid = b.articleid 
where a.articleid<>false; 

//解讀 
新增到 接收表(列1,列2) 
選擇 別名b.列1, 別名a.列2 
從 表1 表名a 聯接 表2 表名b 在 別名a.列c 等於 別名b.列c 
在哪裡 別名a.列c 不等於 沒有 

實際應用中的變通 
select b.tag, a.articleid, a.classid, a.nclassid 
from article as a inner join tag as b on a.articleid = b.articleid 
where a.classid=24; 

查詢 
select b.tag, a.articleid 
from article as a inner join tag as b on a.articleid = b.articleid 
where a.articleid<>false; 

//解讀 
選擇 別名b.列, 別名a.列 
從 表1 別名a 聯接 表2 別名b 在 別名a.列c = 別名b.列c 
在哪裡 別名a.列c 不等於 沒有 
注: as 不是必要