SQLのLEFT JOINで初心者の時に気をつけておいたほうがいいこと

sqlのleft joinの動きをあまり理解していない時に間違った結合してしまいがちでしたので、その時に解決した方法です。

MySQL使ってます。 以下のテーブルでみます。

CREATE TABLE `tiku` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `taisyo_flg` int DEFAULT 0 NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8mb4;

insert into tiku values
(null,'北海道',1),
(null,'関東',1),
(null,'関西',0),
(null,'近畿',1),
(null,'九州',0);

CREATE TABLE `customer` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `tiku_id` int unsigned NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8mb4;

insert into customer values
(null,1,'田中'),
(null,1,'佐藤'),
(null,1,'佐々木'),
(null,2,'鈴木'),
(null,2,'村田'),
(null,3,'木村'),
(null,4,'前田'),
(null,5,'吉田'),
(null,5,'田村')

まず普通に顧客テーブル(customer)に、地区テーブル(tiku)を外部結合して、顧客に対する地区の情報を見る

f:id:okumuraa1:20171210185443p:plain


それに対して、顧客名は全て出力するが、 地区名は、taisyo_flgが1のものについては、地区名を表示し、 taisyo_flgが0のものについてはNULLで出力したい場合があるとする。


select *
from customer
left join tiku
on customer.tiku_id=tiku.id
where tiku.taisyo_flg = 1

上のようにwhereで絞る方法では、当然、taisyo_flgが1のものだけが選ばれてしまい、 顧客名を全て出力するという条件を満たせません

f:id:okumuraa1:20171210190104p:plain


とりあえず私の中では2つ方法があるかと思いました。

1. left joinのジョインキーの部分でやる

select *
from customer
left join tiku
on customer.tiku_id=tiku.id
and tiku.taisyo_flg = 1
order by customer.id

f:id:okumuraa1:20171210190520p:plain

ジョインキーはandで複数指定できるので、 andでtiku.taisyo_flg=1とすれば、顧客名を全て出しつつ、taissyo_flgが1のものだけ地区名を出す動きになってくれるようです。

2. サブクエリにする

select *
from customer
left join (
    select *
    from tiku
    where taisyo_flg = 1
) tiku
on customer.tiku_id=tiku.id
order by customer.id

f:id:okumuraa1:20171210190828p:plain

個人的には、こっちのやり方のほうが見た目どういう動きかわかりやすいと思います。 サブクエリでwhere taisyo_flg = 1と絞っているので、そこに外部結合してもtaisyo_flgが0のものは持って来ようがないという感じで。

SQLをちょっと勉強したという時は、この辺の動作がわかりにくかったのを思い出して書かせていただきました。 最後まで読んでいただきありがとうございました。