SQL | 中間テーブルと暗黙ソート

SQL

SQLの勉強記録です

参考書籍「達人に学ぶ SQL徹底指南書」

つまみ読みした所のメモです。

中間テーブルテーブル

サブクエリの実行結果を中間テーブルとして生成するので、中間テーブルは少ないほど良い

HAVING句を利用する

苦手意識を持っているhavingです。集約結果に対して条件を与えたい場合に利用します。

「HAVING句を利用しないで、2件以上の購入履歴があるユーザーを出力する」という例でやっていきます。

ユーザーごとに何件購入したかは以下のようにシンプルです

SELECT 
	NAME,COUNT(*)
FROM sales
GROUP BY NAME

ここで2件以上という条件を持ったユーザーにするには

SELECT 
	*
FROM (
		SELECT name,COUNT(*) AS cnt
		FROM sales
		GROUP BY name
	) tmp
WHERE cnt >= 2

結果は満足ですが、サブクエリを使って一度中間テーブルを作成しています。
having句を使って書くと中間テーブルの作成がされません。

SELECT 
	NAME,COUNT(*)
FROM sales
GROUP BY NAME
HAVING COUNT(*) >= 2

こっちの方がシンプルなうえに効率も良いです

DISTINCTよりもEXISTS

アニメのタイトルに登場したキャラクターIDを取得するSQLです

SELECT id
FROM characters ch
INNER JOIN anime an
ON ch.id = an.character_id

構造はどうであれ重複が発生しているのでDISTINCTの出番です

SELECT distinct id
FROM characters ch
INNER JOIN anime an
ON ch.id = an.character_id

うまく重複が消えていますが、この時に暗黙的なソートが行われており、パフォーマンスに影響を与えることがあります。

EXISTSを利用して同じ結果が得られるだけでなくソートも発生しません

SELECT id
FROM characters ch
WHERE EXISTS (SELECT * FROM anime an WHERE an.character_id = ch.id)

ちなみにIN句でも同じことができます

SELECT id
FROM characters ch
WHERE id in (SELECT character_id FROM anime)

ただしIN句でサブクエリを利用する場合は、EXISTSにパフォーマンスで劣っているので、EXISTSを利用するのが良いです。

  • IN句はインデックスを参照しない
  • EXISTSは一行でも条件に合致する行を見つけたら検索を止めてくれます
  • IN句ではワークテーブルが作成される

コメント

タイトルとURLをコピーしました