MySQLの3つの関連クエリー方式の簡単な比較

4623 ワード

次の3つの関連クエリのSQL文の違いを見てみましょう. 

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

最大の違いは文法糖が多いが、興味深いものが注目されている.
区別を容易にするために、前の2つの書き方をANSIスタイル、3つ目をThetaスタイルと呼びます.Thetaスタイル
FROMフレーズには関連するテーブル名がリストされ、WHEREフレーズはどのように関連するかを指定します.
このような書き方は古い方式とされていますが、理解しにくい場合があります.以下の検索を見てください.

SELECT * FROM film, film_actor WHERE film.film_id = film_actor.film_id AND actor_id = 17 AND film.length > 120

上記のクエリーには、俳優番号が17の条件を含む120分以上の映画がリストされています.クエリーの結果は気にしないで、クエリー自体はどうですか?WHERE式には3つの条件が含まれており、どの条件が関連しているのか、どの条件がフィルタリングされているのか、それとも少し手間がかかるのかを見ることができます.しかし、比較的簡単ですが、5つのテーブルであれば、20以上の条件がありますか?ANSIスタイル:ON
JOINを使う...ON表に関連付けられた条件と記録フィルタ条件を分けることができ、上記の文を書き換えた結果は以下の通りである.

SELECT * FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) WHERE actor_id = 17 AND film.length > 120

はっきり見える.
注意:ON文の中の括弧は必須ではありません.個人的にはこのように書くのが好きです.
ANSIスタイル:USING
2つの関連テーブルのフィールド名が同じ場合、USINGを使用してSQL文の長さを減らすことができます.

SELECT * FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120

この時は括弧が必要です.この書き方はよく、より少ない単語を入力し、クエリーの性能も素晴らしいですが、違いに注意する必要があります.
USINGとON
次の文は実行可能です.

SELECT film.title, film_id FROM film JOIN film_actor USING (film_id) WHERE actor_id = 17 AND film.length > 120;

しかし、次はだめです.

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

USINGはfilm_idフィールドは両方のテーブルにあるので、正確なテーブルを指定していなくても大丈夫です.両方の値が一致しなければなりません.
ONはそれほどスマートではありません.関連するテーブルとフィールド名を指定する必要があります.
上記の2つの実際の結果は興味深いもので、USINGを使用すると、フィールドは結果に1回しか表示されません.

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を使用すると、フィールドが2回表示されます.

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は両者の処理方法が同じであり、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)
 
[email protected]> 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)
        )

最終的にすべてのクエリーがThetaスタイルに変更されました.
この三つの方法は、書き方の違い以外に何の違いもないということです.