Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

SQLのINとEXISTSの違い

ユーザーテーブルと、そのユーザーが好きなプログラミング言語というテーブルがあるとします。

ユーザーテーブル(UserTable)
id name
1 山田
2 村上
3 中村
好きなプログラミング言語テーブル(FavLangTable)
id user_id lang
1 1 Python
2 1 PHP
3 2 TypeScript
4 2 C#
5 2 Java
6 3 TypeScript

INとEXISTSの使い分け

結合先のレコードを全て欲しい場合は、EXISTS。そうでない場合は、INを使う。
TypeScriptが好きなユーザーを引いてくるSQLをINで書くとこうなる。

SELECT
	ut.name,
         f.lang
FROM
	user_table AS ut
	JOIN fav_lang_table AS f
	ON f.user_id = ut.id
WHERE
	f.lang IN("TypeScript")

結合先をINで絞っているので、そのレコードのみが返却されるため、こうなる。

name lang
村上 TypeScript
中村 TypeScript

TypeScriptが好きなユーザーを抽出するならこれでいい。だが、TypeScriptが好きなユーザーの「他の全てのプログラミング言語」を同時に取得したい場合、うまくいかない。結合先をINで絞り込んでしまうと、結合先のレコードしか取得しないので。

こーゆー時は、EXISTSの出番。EXISTSはそのレコードの存在有無だけを見てくれるので、JOINした結合先のレコードを丸々取ってくる。

SELECT
	ut.username,
         f.lang
FROM
	user_table AS ut
	JOIN fav_lang_table AS f
	ON f.user_id = ut.id
WHERE
	EXISTS (
		SELECT 
			* 
		FROM 
			fav_lang_table AS f1 
        WHERE 
        	f1.lang IN("TypeScript")
        AND
        	f1.user_id = ut.id
)

こうなる。

name lang
村上 TypeScript
村上 C#
村上 Java
中村 TypeScript

EXISTSはINに比べると可読性が下がる(ぱっと見て内容がわかりにくい)が、使いこなせると楽しいよ。