Navicatブログ

SQLセミジョイン(準結合) Oct 15, 2024 by Robert Gravelle

ほとんどのデータベース開発者や管理者は、標準的な内部結合、外部結合、左外部結合、右外部結合のタイプに精通しています。これらはANSI SQLを使用して記述できますが、SQLに構文表現のない関係代数演算子に基づく他のタイプの結合もあります。今日は、そのような結合タイプの一つであるセミジョインについて見ていきます。来週は、同様のアンチジョインについて説明します。これらのタイプの結合の仕組みをよりよく理解するために、Navicat Premium Lite 17でPostgreSQLのdvdrental databaseLECTクエリを実行します。これは、MySQLのSakilaサンプルデータベースに基づいた無料のデータベースです。

セミジョインの説明

ANSI SQLがセミジョインをサポートしていたとしましょう。もしそうであれば、構文はCloudera Impalaの構文拡張であるLEFT SEMI JOINおよびRIGHT SEMI JOINと同様のものになるでしょう。それを念頭に置いて、セミジョインを利用したクエリは次のようになります。

SELECT *
FROM actor
LEFT SEMI JOIN film_actor USING (actor_id)

上記のクエリは、映画に出演したすべての俳優を返します。注意点としては、結果に映画を含めたくない、また同じ俳優の複数の行も必要ないということです。結果には各俳優を1回だけ(または0回)表示したいのです。「セミ」という言葉はラテン語に由来し、英語では「半分」を意味します。したがって、このクエリは「結合の半分」、この場合は左半分だけを実装しています。SQLでは、セミジョインを実現するために使用できる代替構文が2つあります。EXISTSとINです。

EXISTSを使用したセミジョイン

EXISTSを使用したセミジョインと同等のクエリを以下に示します。

SELECT *
FROM actor a
WHERE EXISTS (
  SELECT * 
  FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

Navicat Premium Lite 17でクエリを実行すると、期待通りに動作することがわかります。

semi_join_exists (147K)

結合を使用するのではなく、EXISTS演算子はfilm_actorテーブル内の各アクターについて1つ以上の行が存在するかどうかを確認します。WHERE句のおかげで、ほとんどのデータベースは通常のEXISTS()述語ではなくSEMI JOINを実行していることを認識できます。

INを使用したセミジョイン

INとEXISTSは完全に同等のSEMI JOINエミュレーションであるため、次のクエリは、ほとんどのデータベースで前のEXISTSクエリとまったく同じ結果を生成します。

SELECT *
FROM actor
WHERE actor_id IN (
  SELECT actor_id FROM film_actor
)
Navicat Premium Lite 17での結果を示します。

semi_join_in (157K)

EXISTSは、より強力な(ただし少し冗長な)構文であると考えられています。

Concまとめlusion

今日のブログでは、ANSI SQL構文を使用してセミジョインをエミュレートする方法を学びました。「正確さ」の観点から最適なソリューションであることに加えて、「SEMI」JOINを使用すると、データベースが最初の一致を見つけるとすぐに検索を停止できるため、INNER JOINよりもパフォーマンス上の利点もあります。

Navicat Premium Lite 17をお試しになりませんか?Windows、macOS、Linuxオペレーティングシステムに対応した14日間のフル機能の無料トライアル版をダウンロードできます。

ブログのアーカイブ
シェア