基本に戻ろう: アンチジョインとセミジョイン
参照元:Back to basics: anti-joins and semi-joins < Eddie Awad’s Blog
— beginning of translation —
この記事はOracle結合シリーズの中の一つです。
目次:
1.基本に戻ろう: クロス結合
2.基本に戻ろう: 内部結合
3.基本に戻ろう: 外部結合
4.基本に戻ろう: 等価結合と非等価結合
5.基本に戻ろう: 自己結合
6.基本に戻ろう: アンチジョインとセミジョイン
Oracle結合シリーズがまだ完結していないということを忘れるところでした。いよいよ最終回、アンチ結合と半結合について手短に解説します。
アンチ結合:
アンチ結合はNOT EXISTS句やNOT IN句を用いて記述します。2つの表をアンチ結合した場合、最初に記述された表に存在し、後に記述された表には存在しない行を戻します。つまり、右側の副問合せとの結合に失敗した行を戻すということです。
所属する従業員がいない部署を表示するのであれば、次のように問合せることができます:
SELECT d.department_name
FROM departments d
MINUS
SELECT d.department_name
FROM departments d, employees e
WHERE d.department_id = e.department_id
ORDER BY department_name;
上記の文でも条件に合う結果を得ることができますが、アンチ結合を使った方がよりわかり易く表すことができます:
SELECT d.department_name
FROM departments d
WHERE NOT EXISTS (SELECT NULL
FROM employees e
WHERE e.department_id = d.department_id)
ORDER BY d.department_name;
半結合:
半結合はEXISTS句やIN句を用いて記述します。2つの表を半結合した場合、最初に記述された表に存在する行で、後に記述された表に1行ないしは複数行存在する行を戻します。半結合と従来の結合との違いは、最初に記述される表の行と一致する行が後に記述される表に複数行存在する場合でも1行しか戻されないという点です。
所属する従業員が存在する部署を選択するのであれば、次のように問合せることができます:
SELECT d.department_name
FROM departments d, employees e
WHERE d.department_id = e.department_id
ORDER BY department_name;
上記の問合せ結果では、部署名がその部署に所属する従業員の人数分表示されてしまいます。例えば、従業員が30人所属する部署があった場合、問合せ結果には30件同じ部署名が表示されることになります。
重複行を取除くためには、キーワードDISTINCTやGROUP BYを使えばよいのですが、より簡潔に書くのであれば、従来の結合構文の代わりに半結合を使って部署と従業員を結合します:
SELECT d.department_name
FROM departments d
WHERE EXISTS (SELECT NULL
FROM employees e
WHERE e.department_id = d.department_id)
ORDER BY d.department_name;
上記の問合せ結果では、所属する従業員が存在する部署が選択されますが、従業員が何人所属していようと、一つの部署は1件しか表示されません。
参考文献:
* Speeding Up Queries with Semi-Joins and Anti-Joins
* Documentation
— end of translation —
You’ve written a very well-written story.
If it’s ok with you, I would like to request permission to use your article as it relates to my obstruction. I will be happy to negotiate to pay you or hire you for this.
With Regards from
Republic Polytechnic