前々回、SQL のそもそもの発想と、言ってみればSQL とは RPG III とかRPG/400 でこんなことできたらいいなぁを実現するものである、ということについて紹介しましたが、
今回は SQL の書き方について、その考え方のコツみたいなものをお話できれば、と思っています。
たとえば、↓ の 2つのSQL はまったく同じことを表現しています。
つまり、まったく同じ結果を返してきますが、"書き方"が異なるわけですね。
①
SELECT A.C1, A.C2, B.C3
FROM T1 A, T2 B
WHERE A.C1 = B.C1②
SELECT A.C1, A.C2, B.C3
FROM T1 A JOIN T2 B ON A.C1 = B.C1
さて、この 2つの書き方、何が違うかご存知ですか??
こういうことから「SQL にはいろんな書き方ができてよくわからない」とか、
「SQL はとっつきにくい」とよく言われるんですよねぇ?!
まず、この2つの違いですが、
単純に言うと、SQL-86(87)/89では①のようにしか書けなかったものが、
SQL-92以降に②のような書き方ができるようになった、ということです。
実質的な大きな違いは、
FROM (で指定するデータの検索元)に SQL-92以前は "テーブル" そのものだけしか指定することができなかったのが、"テーブルとテーブルを結合したもの" を指定できるようになった、ということなんです。
(↓ のようにカッコで囲んでみるとわかりやすくなるのではないでしょうか?
カッコの中で、T1テーブル と T2 テーブルをそれぞれに一致して存在するキーで結合したものを検索元のデータ集合とする、ということを示しています)
②
SELECT A.C1, A.C2, B.C3
FROM (T1 A JOIN T2 B ON A.C1 = B.C1)
もともと FROM 句というのは検索元としての "データの集合" が指定されるところです。
理想的に言えば、何でも "データの集合" なら記述できるべきなのですが、
その一番狭い範囲である "テーブル" そのものしか、この時点のSQL では指定できなかったんですね。
(その当時のデータベース製品の能力的な制約、というのもあるのでしょう)
では、①がなぜ②と同様の結果を出力するのでしょうか?
その理屈を見るために、①から WHERE句をまったく削除して実行してみましょう。
SELECT A.C1, A.C2, B.C3
FROM T1 A, T2 B
各テーブルにに以下のようなデータ(行/レコード)が入っているものとして、実際に実行してみましょう。
T1 (A)
| C1 | C2 |
| 0001 | A |
| 0002 | B |
| 0003 | C |
T2 (B)
| C1 | C3 |
| 0001 | あ |
| 0003 | う |
実行してみると、結果は ↓ のようになります。
| 0001 | A | 0001 | あ |
| 0001 | A | 0003 | う |
| 0002 | B | 0001 | あ |
| 0002 | B | 0003 | う |
| 0003 | C | 0001 | あ |
| 0003 | C | 0003 | う |
要するにありえる組み合わせの全て、が出てきます。
これを「直積」、または「クロス結合」と言います。
つまり、
FROM T1 A, T2 B
テーブルとテーブルを , で区切ると、
列記されたテーブル(ここでは T1 テーブルと T2 テーブル)の総当りの組み合わせすべて、という意味になるんですね。
この総当りの"集合"の中から、T1 と T2 の C1 が等しいものを取り出す、というのが①のSQL の意味になります。
②の方はといえば、
FROM (T1 A JOIN T2 B ON A.C1 = B.C1)
が、そもそも "T1 と T2 の C1 が等しいものの集合" が FROM 句の対象である、ということを示しています。
検索対象として、↓ のようなデータ集合がはじめから考えられているわけですね。
(T1 A JOIN T2 B ON A.C1 = B.C1)
| 0001 | A | 0001 | あ |
| 0003 | C | 0003 | う |
繰り返しになりますがあらためてまとめておくと、
- ①は一回総当りの組み合わせを出し、T1 と T2 の C1 が等しいものを取り出すという発想、
- ②はT1 と T2 の C1 が等しいものをデータの検索元として、そこから全件取り出すという発想
という違いがあります。
FROM 句に "データの集合" が指定できるようになったため、極端に言うと ↓ のような指定の仕方すら可能になっているんですね。
③
SELECT *
FROM (
SELECT A.C1, A.C2, B.C3
FROM T1 A, T2 B
WHERE A.C1 = B.C1
) AS C
まぁ、このように記述することはほとんどないと思いますが …
話を元に戻しましょう。
①と②を比較すると、やはり②の方がよりSQL らしい書き方とは言えます。
これにWHERE 句での条件がさらに加わるようなケースでは、
①ですとテーブルを結合させるための条件と、データを選択するための条件がごちゃまぜになってしまいます。
②の場合は、すっきりと結合条件とデータの選択条件を分けて記述することができます。
そうした可読性の観点からも②の方がおすすめの書き方になります。
「SQL はRPG/400 の究極のかたち?! 」でも見たように FROM 句は F 仕様書です。
言ってみれば F 仕様書で、自由に結合論理ファイルの定義ができるようなものですね。
今までつちかったRPG のセンスを生かしてSQL もわかりやすく書くようにすれば、システムにとっても最適化がより簡単にできて、ひょっとしたら実行時間も短縮できるかも?! ですよ!!
この記事にはトラックバック・コメントがありません。
コメントは投稿者の責任においてなされるものであり,サイト管理者は責任を負いません。