MySQL中三種關(guān)聯(lián)查詢(xún)方式的簡(jiǎn)單比較
看看下面三個(gè)關(guān)聯(lián)查詢(xún)的 SQL 語(yǔ)句有何區(qū)別?
SELECT * FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) SELECT * FROM film JOIN film_actor USING (film_id) SELECT * FROM film, film_actor WHERE film.film_id = film_actor.film_id
最大的不同更多是語(yǔ)法糖,但有一些有意思的東西值得關(guān)注。
為了方便區(qū)別,我們將前兩種寫(xiě)法稱(chēng)作是 ANSI 風(fēng)格,第三種稱(chēng)為 Theta 風(fēng)格。
Theta 風(fēng)格
在 FROM 短語(yǔ)中列出了關(guān)聯(lián)的表名,而 WHERE 短語(yǔ)則指定如何關(guān)聯(lián)。
這種寫(xiě)法被認(rèn)為是古老的方式,有些時(shí)候比較難以理解,請(qǐng)看下面查詢(xún):
SELECT * FROM film, film_actor WHERE film.film_id = film_actor.film_id AND actor_id = 17 AND film.length > 120
上述查詢(xún)列出片長(zhǎng)超過(guò) 120 分鐘的電影,其中包括演員編號(hào)是 17 的條件。別在意查詢(xún)結(jié)果,查詢(xún)本身如何呢?WHERE 表達(dá)式中包含三個(gè)條件,要看出哪個(gè)條件是關(guān)聯(lián),哪個(gè)條件是過(guò)濾還是稍費(fèi)點(diǎn)事的。不過(guò)還是相對(duì)簡(jiǎn)單的,但如果是 5 個(gè)表,20 多個(gè)條件呢?
ANSI 風(fēng)格: ON
使用 JOIN ... ON 可以將表關(guān)聯(lián)的條件和記錄過(guò)濾條件分開(kāi),將上面的語(yǔ)句重寫(xiě)后的結(jié)果如下:
SELECT * FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) WHERE actor_id = 17 AND film.length > 120
看起來(lái)清晰許多。
注意: ON 語(yǔ)句中的括號(hào)不是必須的,我個(gè)人喜歡這樣寫(xiě)而已。
ANSI 風(fēng)格: USING
有一種特殊情況,當(dāng)兩個(gè)要關(guān)聯(lián)表的字段名是一樣的,我們可以使用 USING ,可減少 SQL 語(yǔ)句的長(zhǎng)度:
SELECT * FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120
這個(gè)時(shí)候括號(hào)就是必須的了。這種寫(xiě)法很好,輸入更少的單詞,查詢(xún)的性能也非常棒,但還需要注意一些差異。
USING 和 ON
下面語(yǔ)句是可行的:
SELECT film.title, film_id FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120;
但下面這個(gè)就不行:
SELECT film.title, film_id FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) WHERE actor_id = 17 AND film.length > 120;ERROR 1052 (23000): Column 'film_id' in field list is ambiguous
因?yàn)?USING "知道" film_id 字段在兩個(gè)表中都有,所以沒(méi)有指定確切的表都沒(méi)關(guān)系,兩個(gè)值必須一致就是。
ON 就沒(méi)那么智能,你必須指明要關(guān)聯(lián)的表和字段名。
上面兩個(gè)實(shí)際的結(jié)果是比較有趣的,當(dāng)使用 USING 時(shí),字段只在結(jié)果中出現(xiàn)一次:
SELECT * FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120 LIMIT 1\G *************************** 1. row *************************** film_id: 96 title: BREAKING HOME description: A Beautiful Display of a Secret Agent And a Monkey who must Battle a Sumo Wrestler in An Abandoned Mine Shaft release_year: 2006 language_id: 1 original_language_id: NULL rental_duration: 4 rental_rate: 2.99 length: 169 replacement_cost: 21.99 rating: PG-13 special_features: Trailers,Commentaries last_update: 2006-02-15 05:03:42 actor_id: 17 last_update: 2006-02-15 05:05:03
而使用 ON 時(shí),字段就會(huì)出現(xiàn)兩次:
SELECT * FROM film JOIN film_actor ON film.film_id = film_actor.film_id WHERE actor_id = 17 AND film.length > 120 LIMIT 1\G *************************** 1. row *************************** film_id: 96 title: BREAKING HOME description: A Beautiful Display of a Secret Agent And a Monkey who must Battle a Sumo Wrestler in An Abandoned Mine Shaft release_year: 2006 language_id: 1 original_language_id: NULL rental_duration: 4 rental_rate: 2.99 length: 169 replacement_cost: 21.99 rating: PG-13 special_features: Trailers,Commentaries last_update: 2006-02-15 05:03:42 actor_id: 17 film_id: 96 last_update: 2006-02-15 05:05:03
幕后
MySQL 對(duì)兩者的處理方式是相同的,使用 EXPLAIN EXTENDED 我們可以看到:
EXPLAIN EXTENDED SELECT film.title, film_id FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120\G *************************** 1. row *************************** ... 2 rows in set, 1 warning (0.00 sec) root@mysql-5.1.51> SHOW WARNINGS\G *************************** 1. row *************************** Level: Note Code: 1003 Message: select `sakila`.`film`.`title` AS `title`,`sakila`.`film`.`film_id` AS `film_id` from `sakila`.`film` join `sakila`.`film_actor` where ( (`sakila`.`film`.`film_id` = `sakila`.`film_actor`.`film_id`) and (`sakila`.`film_actor`.`actor_id` = 17) and (`sakila`.`film`.`length` > 120) )
最終所有的查詢(xún)都被轉(zhuǎn)成了 Theta 風(fēng)格。
譯者:就是說(shuō)這三種方式除了寫(xiě)法不同外,沒(méi)什么區(qū)別。
相關(guān)文章
MySQL的InnoDB存儲(chǔ)引擎的數(shù)據(jù)頁(yè)結(jié)構(gòu)詳解
這篇文章主要為大家詳細(xì)介紹了MySQL的InnoDB存儲(chǔ)引擎的數(shù)據(jù)頁(yè)結(jié)構(gòu),,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03MySQL處理重復(fù)數(shù)據(jù)的學(xué)習(xí)筆記
在本篇文章里小編給大家分享的是一篇關(guān)于MySQL處理重復(fù)數(shù)據(jù)的學(xué)習(xí)筆記,需要的朋友們可以參考下。2020-03-03解析MSSQL跨數(shù)據(jù)庫(kù)查詢(xún)的實(shí)現(xiàn)方法
本篇文章是對(duì)MSSQL跨數(shù)據(jù)庫(kù)查詢(xún)的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06MySQL數(shù)據(jù)庫(kù)多表聯(lián)合查詢(xún)代碼示例
所謂聯(lián)合就是把多個(gè)表的記錄往一起合并,一起進(jìn)行查詢(xún),也叫多表查詢(xún),這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫(kù)多表聯(lián)合查詢(xún)的相關(guān)資料,需要的朋友可以參考下2024-01-01一篇文章帶你輕松了解MySQL之事務(wù)的簡(jiǎn)介
事務(wù)可以由一條非常簡(jiǎn)單的SQL語(yǔ)句組成,也可以由一組復(fù)雜的SQL語(yǔ)句組成,事務(wù)的目的是將數(shù)據(jù)庫(kù)從一種一致性狀態(tài)轉(zhuǎn)換為另一種一致性狀態(tài),下面這篇文章主要給大家介紹了關(guān)于MySQL事務(wù)簡(jiǎn)介的相關(guān)資料,需要的朋友可以參考下2023-06-06mysql的join查詢(xún)和多次查詢(xún)方式比較
這篇文章主要介紹了mysql的join查詢(xún)和多次查詢(xún)方式的比較,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03