MySQL的聯(lián)結(jié)(Join)語(yǔ)法1.內(nèi)聯(lián)結(jié)、外聯(lián)結(jié)、左聯(lián)結(jié)、右聯(lián)結(jié)的含義及區(qū)別: 在講MySQL的Join語(yǔ)法前還是先回顧一下聯(lián)結(jié)的語(yǔ)法,呵呵,其實(shí)連我自己都忘得差不多了,那就大家一起溫習(xí)吧(如果內(nèi)容有錯(cuò)誤或有疑問(wèn),可以來(lái)信咨詢:陳朋奕 chenpengyi#gmail.com),國(guó)內(nèi)關(guān)于MySQL聯(lián)結(jié)查詢的資料十分少,相信大家在看了本文后會(huì)對(duì)MySQL聯(lián)結(jié)語(yǔ)法有相當(dāng)清晰的了解,也不會(huì)被Oracle的外聯(lián)結(jié)的(“+”號(hào))弄得糊涂了。 在SQL標(biāo)準(zhǔn)中規(guī)劃的(Join)聯(lián)結(jié)大致分為下面四種: 1. 內(nèi)聯(lián)結(jié):將兩個(gè)表中存在聯(lián)結(jié)關(guān)系的字段符合聯(lián)結(jié)關(guān)系的那些記錄形成記錄集的聯(lián)結(jié)。 2. 外聯(lián)結(jié):分為外左聯(lián)結(jié)和外右聯(lián)結(jié)。 左聯(lián)結(jié)A、B表的意思就是將表A中的全部記錄和表B中聯(lián)結(jié)的字段與表A的聯(lián)結(jié)字段符合聯(lián)結(jié)條件的那些記錄形成的記錄集的聯(lián)結(jié),這里注意的是最后出來(lái)的記錄集會(huì)包括表A的全部記錄。 右聯(lián)結(jié)A、B表的結(jié)果和左聯(lián)結(jié)B、A的結(jié)果是一樣的,也就是說(shuō): Select A.name B.name From A Left Join B On A.id=B.id 和Select A.name B.name From B Right Join A on B.id=A.id執(zhí)行后的結(jié)果是一樣的。 3.全聯(lián)結(jié):將兩個(gè)表中存在聯(lián)結(jié)關(guān)系的字段的所有記錄取出形成記錄集的聯(lián)結(jié)(這個(gè)不需要記憶,只要是查詢中提到了的表的字段都會(huì)取出,無(wú)論是否符合聯(lián)結(jié)條件,因此意義不大)。 4.無(wú)聯(lián)結(jié):不用解釋了吧,就是沒(méi)有使用聯(lián)結(jié)功能唄,也有自聯(lián)結(jié)的說(shuō)法。 這里我有個(gè)比較簡(jiǎn)便的記憶方法,內(nèi)外聯(lián)結(jié)的區(qū)別是內(nèi)聯(lián)結(jié)將去除所有不符合條件的記錄,而外聯(lián)結(jié)則保留其中部分。外左聯(lián)結(jié)與外右聯(lián)結(jié)的區(qū)別在于如果用A左聯(lián)結(jié)B則A中所有記錄都會(huì)保留在結(jié)果中,此時(shí)B中只有符合聯(lián)結(jié)條件的記錄,而右聯(lián)結(jié)相反,這樣也就不會(huì)混淆了。其實(shí)大家回憶高等教育出版社出版的《數(shù)據(jù)庫(kù)系統(tǒng)概論》書(shū)中講到關(guān)系代數(shù)那章(就是將笛卡兒積和投影那章)的內(nèi)容,相信不難理解這些聯(lián)結(jié)功能的內(nèi)涵。 2. MySQL聯(lián)結(jié)(Join)的語(yǔ)法 MySQL支持Select和某些Update和Delete情況下的Join語(yǔ)法,具體語(yǔ)法上的細(xì)節(jié)有: table_references: table_reference [, table_reference] … table_reference: table_factor | join_table table_factor: tbl_name [[AS] alias] [{USE|IGNORE|FORCE} INDEX (key_list)] | ( table_references ) | { OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr } join_table: table_reference [INNER | CROSS] JOIN table_factor [join_condition] | table_reference STRAIGHT_JOIN table_factor | table_reference STRAIGHT_JOIN table_factor ON condition | table_reference LEFT [OUTER] JOIN table_reference join_condition | table_reference NATURAL [LEFT [OUTER]] JOIN table_factor | table_reference RIGHT [OUTER] JOIN table_reference join_condition | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor join_condition: ON conditional_expr | USING (column_list) 上面的用法摘自權(quán)威資料,不過(guò)大家看了是否有點(diǎn)暈?zāi)??呵呵,?yīng)該問(wèn)題主要還在于table_reference是什么,table_factor又是什么?這里的table_reference其實(shí)就是表的引用的意思,因?yàn)樵?/SPAN>MySQL看來(lái),聯(lián)結(jié)就是一種對(duì)表的引用,因此把需要聯(lián)結(jié)的表定義為table_reference,同時(shí)在SQL Standard中也是如此看待的。而table_factor則是MySQL對(duì)這個(gè)引用的功能上的增強(qiáng)和擴(kuò)充,使得引用的表可以是括號(hào)內(nèi)的一系列表,如下面例子中的JOIN后面括號(hào): SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c) 這個(gè)語(yǔ)句的執(zhí)行結(jié)果和下面語(yǔ)句其實(shí)是一樣的: SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c) 這兩個(gè)例子不僅讓我們了解了MySQL中table_factor和table_reference含義,同時(shí)能理解一點(diǎn)CROSS JOIN的用法,我要補(bǔ)充的是在MySQL現(xiàn)有版本中CROSS JOIN的作用和INNER JOIN是一樣的(雖然在SQL Standard中是不一樣的,然而在MySQL中他們的區(qū)別僅僅是INNER JOIN需要附加ON參數(shù)的語(yǔ)句,而CROSS JOIN不需要)。 既然說(shuō)到了ON語(yǔ)句,那就解釋一下吧,ON語(yǔ)句其實(shí)和WHERE語(yǔ)句功能大致相當(dāng),只是這里的ON語(yǔ)句是專門針對(duì)聯(lián)結(jié)表的,ON語(yǔ)句后面的條件的要求和書(shū)寫(xiě)方式和WHERE語(yǔ)句的要求是一樣的,大家基本上可以把ON當(dāng)作WHERE用。 大家也許也看到了OJ table_reference LEFT OUTER JOIN table_reference這個(gè)句子,這不是MySQL的標(biāo)準(zhǔn)寫(xiě)法,只是為了和ODBC的SQL語(yǔ)法兼容而設(shè)定的,我很少用,Java的人更是不會(huì)用,所以也不多解釋了。 那下面就具體講講簡(jiǎn)單的JOIN的用法了。首先我們假設(shè)有2個(gè)表A和B,他們的表結(jié)構(gòu)和字段分別為: 表A:
表B:
1. 內(nèi)聯(lián)結(jié): Select A.Name B.Hobby from A, B where A.id = B.id,這是隱式的內(nèi)聯(lián)結(jié),查詢的結(jié)果是:
它的作用和 Select A.Name from A INNER JOIN B ON A.id = B.id是一樣的。這里的INNER JOIN換成CROSS JOIN也是可以的。 2. 外左聯(lián)結(jié) Select A.Name from A Left JOIN B ON A.id = B.id,典型的外左聯(lián)結(jié),這樣查詢得到的結(jié)果將會(huì)是保留所有A表中聯(lián)結(jié)字段的記錄,若無(wú)與其相對(duì)應(yīng)的B表中的字段記錄則留空,結(jié)果如下:
所以從上面結(jié)果看出,因?yàn)?/SPAN>A表中的John記錄的ID沒(méi)有在B表中有對(duì)應(yīng)ID,因此為空,但Name欄仍有John記錄。 3. 外右聯(lián)結(jié) 如果把上面查詢改成外右聯(lián)結(jié):Select A.Name from A Right JOIN B ON A.id = B.id,則結(jié)果將會(huì)是:
這樣的結(jié)果都是我們可以從外左聯(lián)結(jié)的結(jié)果中猜到的了。 說(shuō)到這里大家是否對(duì)聯(lián)結(jié)查詢了解多了?這個(gè)原本看來(lái)高深的概念一下子就理解了,恍然大悟了吧(呵呵,開(kāi)玩笑了)?最后給大家講講MySQL聯(lián)結(jié)查詢中的某些參數(shù)的作用: 1.USING (column_list):其作用是為了方便書(shū)寫(xiě)聯(lián)結(jié)的多對(duì)應(yīng)關(guān)系,大部分情況下USING語(yǔ)句可以用ON語(yǔ)句來(lái)代替,如下面例子: a LEFT JOIN b USING (c1,c2,c3),其作用相當(dāng)于下面語(yǔ)句 a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3 只是用ON來(lái)代替會(huì)書(shū)寫(xiě)比較麻煩而已。 2.NATURAL [LEFT] JOIN:這個(gè)句子的作用相當(dāng)于INNER JOIN,或者是在USING子句中包含了聯(lián)結(jié)的表中所有字段的Left JOIN(左聯(lián)結(jié))。 3.STRAIGHT_JOIN:由于默認(rèn)情況下MySQL在進(jìn)行表的聯(lián)結(jié)的時(shí)候會(huì)先讀入左表,當(dāng)使用了這個(gè)參數(shù)后MySQL將會(huì)先讀入右表,這是個(gè)MySQL的內(nèi)置優(yōu)化參數(shù),大家應(yīng)該在特定情況下使用,譬如已經(jīng)確認(rèn)右表中的記錄數(shù)量少,在篩選后能大大提高查詢速度。 最后要說(shuō)的就是,在MySQL5.0以后,運(yùn)算順序得到了重視,所以對(duì)多表的聯(lián)結(jié)查詢可能會(huì)錯(cuò)誤以子聯(lián)結(jié)查詢的方式進(jìn)行。譬如你需要進(jìn)行多表聯(lián)結(jié),因此你輸入了下面的聯(lián)結(jié)查詢: SELECT t1.id,t2.id,t3.id FROM t1,t2 LEFT JOIN t3 ON (t3.id=t1.id) WHERE t1.id=t2.id; 但是MySQL并不是這樣執(zhí)行的,其后臺(tái)的真正執(zhí)行方式是下面的語(yǔ)句: SELECT t1.id,t2.id,t3.id FROM t1,( t2 LEFT JOIN t3 ON (t3.id=t1.id) ) WHERE t1.id=t2.id; 這并不是我們想要的效果,所以我們需要這樣輸入: SELECT t1.id,t2.id,t3.id FROM (t1,t2) LEFT JOIN t3 ON (t3.id=t1.id) WHERE t1.id=t2.id; 在這里括號(hào)是相當(dāng)重要的,因此以后在寫(xiě)這樣的查詢的時(shí)候我們不要忘記了多寫(xiě)幾個(gè)括號(hào),至少這樣能避免很多錯(cuò)誤(因?yàn)檫@樣的錯(cuò)誤是很難被開(kāi)發(fā)人員發(fā)現(xiàn)的)。如果對(duì)上面內(nèi)容有疑問(wèn)可以來(lái)信查詢:陳朋奕 chenpengyi#gmail.com,轉(zhuǎn)載請(qǐng)注明出處及作者。 陳朋奕 2005-10-17 22:53
|
|
來(lái)自: Ralf_Jones > 《數(shù)據(jù)庫(kù)》