goo blog サービス終了のお知らせ 

職業JAVAらーの憂鬱

職業JAVAらーの、世のため人のため以前に、自分のための覚え書き。

SQLerの憂鬱?

2007-10-30 11:05:39 | Weblog
SQLの基礎。

テーブルA
GROUPCD,GROUP
------------
01,motenaiTeam

テーブルB
GROUPCD,ID,NAME
------------
01,AA,javaler
02,BB,sqler

上記テーブルがあって、テーブルAのレコード1件を取得したい場合。

1)
select A.*
from A

ではテーブルAのレコードが正しく抽出される。
しかし、

2)
select A
from A, B

こういう、テーブルBが全く意味をなさないSQLを流したときの話。
予想では1)と同様にAのレコードが1件だけ正しく取得できると思ってたんだけど・・・。
結果として、同一レコードが複数抽出された。

GROUPCD,GROUP
---------------
01,motenaiTeam
01,motenaiTeam

その秘密はテーブルBの使い方にあった。

2)のSQLは、テーブルBは何も使用されていないように見えるが、
実は「inner join」でテーブルAに結合されているらしい!

inner joinをしているが結合条件がないために、
テーブルAのレコード1件に対して、テーブルBの全レコードが結合される。

試しに
select A.*, B.*
from A, B
を流してみると

01,motenaiTeam,01,AA,javaler
01,motenaiTeam,02,BB,sql

こんな感じで、テーブルAの1件にBのレコードが全てくっついて、別レコードとして抽出されてしまうのが確認できる。

2)で同一レコードが複数出てくるように見えたのは、
テーブルAの内容しか表示していなかったからなのだ。

逆にテーブルBのレコードを0件にすると、
1)では1件が正しく取得できたのに対して、
2)では正しく取得できない(該当0件となってしまう)

これは「inner join」の特性を考えると自然なことだった。
inner joinは結合しようとするテーブル(この場合はテーブルB)に、
結合条件に該当するレコードが存在しない場合は、テーブルAのレコードは抽出しないという特性がある。

よって、テーブルBが0件の場合は、当然テーブルAに結合できるデータがないので、該当件数0となってしまう。

☆結論☆
下手なSQLは休日出勤の元。
よ~く考えよ~。
ご利用は計画的に。。。