MySQL查詢分為內(nèi)連接查詢和外連接查詢,他們的區(qū)別在于:內(nèi)連接查詢的兩個(gè)表示對(duì)等關(guān)系,根據(jù)條件進(jìn)行匹配;外連接是以某一個(gè)表為主,兩一個(gè)表根據(jù)條件進(jìn)行關(guān)聯(lián)。外連接分為左外連接、右外連接和全外連接。本文重點(diǎn)介紹各外連接的思想,以及如何實(shí)現(xiàn)全外連接,并舉例。
左外連接以左邊表為基礎(chǔ),根據(jù)條件,將右邊表附屬到左邊表,語(yǔ)法:SELECT * FROM A LEFT JOIN B ON condition。幾何圖形關(guān)系如下圖,即查詢結(jié)果集除了A表所有數(shù)據(jù)外,還包含滿足條件的B表數(shù)據(jù):
右外連接以右邊表為基礎(chǔ),根據(jù)條件,將左邊表附屬到右邊表,語(yǔ)法:SELECT * FROM A RIGHT JOIN B ON condition。幾何圖形關(guān)系如下圖,即查詢結(jié)果集除了B表所有數(shù)據(jù)外,還包含滿足條件的A表數(shù)據(jù):
全外連接是除了能夠根據(jù)條件匹配得到的數(shù)據(jù),還包含左右兩表中都不匹配的數(shù)據(jù)(默認(rèn)應(yīng)為null),應(yīng)用全外連接的情況一般都有一個(gè)聯(lián)系左右兩表的主線。幾何關(guān)系如下圖所示,對(duì)應(yīng)A和B的并集(去重):
但不幸的是MySQL不支持全外連接,那在需要全外連接查詢的情況下,如何實(shí)現(xiàn)呢?最常見(jiàn)的是左連接與右連接合并。
項(xiàng)目中存在這樣的場(chǎng)景:某項(xiàng)任務(wù)task具有2種不同的狀態(tài)todo和done,分別存儲(chǔ)在todolist和donelist表中,任務(wù)存儲(chǔ)在task表中,現(xiàn)在需要統(tǒng)計(jì)每個(gè)task的已處理和未處理情況。首先先到了全外連接,那么如何實(shí)現(xiàn)呢?
舉例實(shí)現(xiàn)表結(jié)構(gòu)如下:
實(shí)現(xiàn)四種方法:
首先是左連接:
1 SELECT 2 A.id AS Aid, 3 B.id AS Bid, 4 A.taskid tid 5 FROM 6 ( 7 SELECT 8 * 9 FROM10 todolist11 WHERE12 todolist.user = '張三'13 ) A14 LEFT JOIN (15 SELECT16 *17 FROM18 donelist19 WHERE20 donelist.user = '張三'21 ) B ON A.taskid = B.taskid
查詢結(jié)果:
其次是右連接(注意由于需要合并,故左右連接的結(jié)果集結(jié)構(gòu)需一致):
1 SELECT 2 A.id AS Aid, 3 B.id AS Bid, 4 A.taskid tid 5 FROM 6 ( 7 SELECT 8 * 9 FROM10 todolist11 WHERE12 todolist.user = '張三'13 ) A14 RIGHT JOIN (15 SELECT16 *17 FROM18 donelist19 WHERE20 donelist.user = '張三'21 ) B ON A.taskid = B.taskid
查詢結(jié)果:
最后進(jìn)行合并,并與task表進(jìn)行內(nèi)連接:
1 SELECT 2 SUM(IF(Aid IS NOT NULL, 1, 0)) todo, 3 SUM(IF(Bid IS NOT NULL, 1, 0)) done, 4 task.name 5 FROM 6 ( 7 SELECT 8 A.id AS Aid, 9 B.id AS Bid,10 A.taskid tid11 FROM12 (13 SELECT14 *15 FROM16 todolist17 WHERE18 todolist.user = '張三'19 ) A20 LEFT JOIN (21 SELECT22 *23 FROM24 donelist25 WHERE26 donelist.user = '張三'27 ) B ON A.taskid = B.taskid28 UNION29 SELECT30 A.id AS Aid,31 B.id AS Bid,32 B.taskid tid33 FROM34 (35 SELECT36 *37 FROM38 todolist39 WHERE40 todolist.user = '張三'41 ) A42 RIGHT JOIN (43 SELECT44 *45 FROM46 donelist47 WHERE48 donelist.user = '張三'49 ) B ON A.taskid = B.taskid50 ) AS AB51 INNER JOIN task ON task.id = AB.tid52 GROUP BY53 task.name
運(yùn)行結(jié)果如下表,實(shí)現(xiàn)全外連接:
這是另一種實(shí)現(xiàn)全外連接的方式,即先查詢A B的左連接,然后查詢B中去除左連接到A的記錄,最后合并(A代表todolist,B代表donelist):
A+B左連接
1 SELECT 2 1 AS todo, 3 CASE 4 WHEN B.id IS NOT NULL THEN 5 1 6 ELSE 7 0 8 END AS done, 9 A.taskid tid 10 FROM11 (12 SELECT13 *14 FROM15 todolist16 WHERE17 todolist.user = '張三'18 ) A19 LEFT JOIN (20 SELECT21 *22 FROM23 donelist24 WHERE25 donelist.user = '張三'26 ) B ON A.taskid = B.taskid
查詢結(jié)果:
B-A去除左連接到A的記錄
1 SELECT 2 0 AS todo, 3 1 AS done, 4 donelist.taskid tid 5 FROM 6 donelist 7 WHERE 8 donelist.user = '張三' 9 AND NOT EXISTS (10 SELECT11 *12 FROM13 todolist14 WHERE15 todolist.taskid = donelist.taskid16 AND donelist.user = '張三'17 AND odolist.user = donelist.user18 )
查詢結(jié)果:
合并
1 SELECT 2 SUM(AB.todo) todo, 3 SUM(AB.done) done, 4 task.name 5 FROM 6 ( 7 SELECT 8 1 AS todo, 9 CASE10 WHEN B.id IS NOT NULL THEN11 112 ELSE13 014 END AS done,15 A.taskid tid16 FROM17 (18 SELECT19 *20 FROM21 todolist22 WHERE23 todolist.user = '張三'24 ) A25 LEFT JOIN (26 SELECT27 *28 FROM29 donelist30 WHERE31 donelist.user = '張三'32 ) B ON A.taskid = B.taskid33 UNION34 SELECT35 0 AS todo,36 1 AS done,37 donelist.taskid tid38 FROM39 donelist40 WHERE41 donelist.user = '張三'42 AND NOT EXISTS (43 SELECT44 *45 FROM46 todolist47 WHERE48 todolist.taskid = donelist.taskid49 AND donelist.user = '張三'50 AND odolist.user = donelist.user51 )52 ) AB53 INNER JOIN task ON task.id = AB.tid54 GROUP BY55 task.name
結(jié)果同上
該方法的思想是,不管A和B表有什么關(guān)系,他們都跟作為主線的表task相關(guān),只需要將A和B表與task表進(jìn)行左連接,得到連接后的數(shù)據(jù)集,即為最后需要查詢的結(jié)果集。SQL代碼如下:
1 SELECT 2 SUM(AB.todo) AS todo, 3 SUM(AB.done) AS done, 4 task.name 5 FROM 6 ( 7 SELECT 8 task.name, 9 CASE10 WHEN A.id IS NULL THEN11 012 ELSE13 114 END AS todo,15 CASE16 WHEN B.id IS NULL THEN17 018 ELSE19 120 END AS done21 FROM22 task23 LEFT JOIN (24 SELECT25 *26 FROM27 todolist28 WHERE29 todolist.user = '張三'30 ) A ON A.taskid = task.id31 LEFT JOIN (32 SELECT33 *34 FROM35 donelist36 WHERE37 donelist.user = '張三'38 ) B ON B.taskid = task.id39 WHERE40 A.id IS NOT NULL41 OR B.id IS NOT NULL42 ) AB43 GROUP BY44 task.name
查詢結(jié)果同上,但這種方法存在一定的缺陷,即當(dāng)主線表(task表)特別大的時(shí)候,性能會(huì)比較差。
該方法是不管A和B表的關(guān)系,現(xiàn)根據(jù)條件查詢,然后在合并。SQL語(yǔ)句如下:
1 SELECT 2 SUM(A.todo) todo, 3 SUM(A.done) done, 4 task.name 5 FROM 6 ( 7 SELECT 8 1 todo, 9 0 done,10 todolist.taskid tid11 FROM12 todolist13 WHERE14 todolist.user = '張三'15 UNION ALL16 SELECT17 0 todo,18 1 done,19 donelist.taskid tid20 FROM21 donelist22 WHERE23 donelist.user = '張三'24 ) A25 INNER JOIN task ON task.id = A.tid26 GROUP BY27 task.name
查詢結(jié)果同上。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
當(dāng)前名稱:數(shù)據(jù)庫(kù)外連接及MySQL實(shí)現(xiàn)-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)地址:http://chinadenli.net/article30/iosso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站建設(shè)、云服務(wù)器、網(wǎng)站制作、動(dòng)態(tài)網(wǎng)站、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容