Oracle11gで+サインインを使用した左外部結合


81

2つ以下のクエリが左外部結合または右外部結合の例であるかどうかを誰かに教えてもらえますか?

Table Part:
Name         Null?       Type
PART_ID      NOT NULL    VARCHAR2(4)
SUPPLIER_ID              VARCHAR2(4)

PART_ID SUPPLIER_ID
P1      S1
P2      S2
P3  
P4  

Table Supplier:
Name            Null?     Type
SUPPLIER_ID NOT NULL      VARCHAR2(4)
SUPPLIER_NAME   NOT NULL  VARCHAR2(20)

SUPPLIER_ID  SUPPLIER_NAME
S1           Supplier#1
S2           Supplier#2
S3           Supplier#3

サプライヤが部品を供給しているかどうかに関係なく、すべての部品を表示します。

SELECT P.Part_Id、S.Supplier_Name
パートP、サプライヤーSから
WHERE P.Supplier_Id = S.Supplier_Id(+)

SELECT P.Part_Id、S.Supplier_Name
パートP、サプライヤーSから
WHERE S.Supplier_Id(+)= P.Supplier_Id

26
'(+)'表記の使用を避け、明示的な結合を使用するようにクエリをアップグレードする必要があります。
ジョナサンレフラー2011

1
@JonathanLeffler 100%同意します。問題は、私が標準的な表記法に切り替えたくない人々と仕事をしていることです。私は標準的な表記法で新しいクエリを作成しますが、古いクエリを変更した場合はすぐに撮影されます。
Luc M

3
@JonathanLeffler Oracleを使用していない限り、同意します。現在のOracleは、ansi構文と(+)演算子を内部で処理しません。彼らはansi構文の使用を推奨していますが:)docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
神話

7
@Amythこのように古いコメントで申し訳ありませんが、私は検索からこの質問に行きました。私自身、オラクルの推奨事項を正反対の方法で理解しています。リンクから:Oracleでは、Oracle結合演算子ではなくFROM句のOUTER JOIN構文を使用することをお勧めします。Oracle結合演算子(+)を使用する外部結合クエリには、次の規則と制限が適用されますが、これらは適用されません。 FROM句OUTERJOIN構文... "
Sylvain Leroux 2014年

応答が古くなって申し訳ありません:)しかし、オラクルが言っていることと、クエリを最適化するために統計がどのように機能するかは2つの異なるものであり、オラクルが内部オプティマイザーの進歩とともにスタンスも変更した可能性があります
神話

回答:


188

TableA LEFT OUTER JOIN TableBと同等TableB RIGHT OUTER JOIN Table Aです。

Oracleでは(+)、JOINの「オプション」テーブルを示します。したがって、最初のクエリでは、それはP LEFT OUTER JOIN Sです。2番目のクエリでは、S RIGHT OUTER JOIN Pです。それらは機能的に同等です。

用語では、RIGHTまたはLEFTは、結合のどちら側に常にレコードがあるかを指定し、反対側はnullになる可能性があります。そうでP LEFT OUTER JOIN SPそれは上だから、常に、レコードを持っていますLEFTが、Snullになる可能性があります。

追加の説明については、java2s.comのこの例を参照してください。


明確にするために、用語は重要ではないと言っていると思います。用語は視覚化に役立つだけだからです。重要なのは、それがどのように機能するかの概念を理解していることです。


右vs左

暗黙的な結合構文でRIGHTとLEFTを決定する際に重要なことについて混乱が見られました。

左外部結合

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外部結合

SELECT *
FROM A, B
WHERE B.column(+) = A.column

WHERE句の用語の側面を入れ替えるだけですが、機能的には同等です。(詳細については、私の回答の上位を参照してください。)(+)決定の配置はRIGHTまたはLEFTを決定します。(具体的に(+)は、が右側にある場合(+)は左結合です。が左側にある場合は右結合です。)


JOINの種類

JOINの2つのスタイルは、暗黙的なJOIN明示的なJOINです。これらはJOINの記述スタイルが異なりますが、機能的には同等です。

このSOの質問を参照してください。

暗黙的なJOINは、単にすべてのテーブルを一緒にリストします。結合条件はWHERE句で指定されます。

暗黙的な結合

SELECT *
FROM A, B
WHERE A.column = B.column(+)

明示的なJOINは、WHERE句ではなく、特定のテーブルの包含に結合条件を関連付けます。

明示的結合

SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column

これらの暗黙的なJOINは、読みやすく理解しにくい場合があります。また、結合条件が他のWHERE条件に混在しているため、いくつかの制限があります。そのため、明示的な構文を優先して、暗黙的なJOINを使用しないことをお勧めします。


3
そうです、私は今それを理解しています-JOINは(+)の存在によって暗黙的に作成されます。涼しい。
Kerrek SB 2011

2
@Mike:それが+構文の仕組みです。これは「オプション」を意味するので、「すべての部品をリストし、オプションでサプライヤーを一致させる」のように読んでください。
Kerrek SB 2011

2
@マイク:あなたが何を選択しているのかを知っている限り、それをどのように呼ぶかは実際には問題ではありません。しかし、自分に有利に働き、JOIN代わりに慣用的な構文を使用してください!そうすれば、混乱の余地はありません。
Kerrek SB 2011

1
@TomJMuthirenthi明示的なFULL OUTER JOIN構文を使用せずに、UNION [ALL]2つの結果セットを一緒に作成する必要があります。1つはA = B(+)用、もう1つはB = A(+)用です。この質問の例。
Wiseguy 2017年

1
「(+)」は、nullのサブ行を生成するテーブルの列に表示されます。
philipxy 2017年

9

これらの2つのクエリは実行していOUTER JOINます。下記参照

Oracleの結合演算子ではなく、FROM句のOUTERJOIN構文を使用することをお勧めします。Oracle結合演算子(+)を使用する外部結合クエリには、FROM句のOUTERJOIN構文には適用されない次の規則と制限が適用されます。

  • FROM句の結合構文も含むクエリブロックで(+)演算子を指定することはできません。

  • (+)演算子は、WHERE句、またはFROM句の左相関(TABLE句を指定する場合)のコンテキストでのみ表示でき、テーブルまたはビューの列にのみ適用できます。

  • AとBが複数の結合条件で結合されている場合は、これらすべての条件で(+)演算子を使用する必要があります。そうしないと、Oracle Databaseは単純結合の結果の行のみを返しますが、外部結合の結果がないことを通知する警告やエラーは表示されません。

  • (+)演算子は、外部クエリで1つのテーブルを指定し、内部クエリで他のテーブルを指定した場合、外部結合を生成しません。

  • 自己結合は有効ですが、(+)演算子を使用してテーブルをそれ自体に外部結合することはできません。たとえば、次のステートメントは無効です。

    -- The following statement is not valid:
    SELECT employee_id, manager_id
       FROM employees
       WHERE employees.manager_id(+) = employees.employee_id;
    

    ただし、次の自己結合は有効です。

    SELECT e1.employee_id, e1.manager_id, e2.employee_id
       FROM employees e1, employees e2
       WHERE e1.manager_id(+) = e2.employee_id
       ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
    
  • (+)演算子は列にのみ適用でき、任意の式には適用できません。ただし、任意の式には、(+)演算子でマークされた1つ以上の列を含めることができます。

  • (+)演算子を含むWHERE条件は、OR論理演算子を使用して別の条件と組み合わせることができません。

  • WHERE条件では、IN比較条件を使用して、(+)演算子でマークされた列を式と比較することはできません。

WHERE句にテーブルBの列を定数と比較する条件が含まれている場合、Oracleがこの列に対してnullを生成したテーブルAの行を返すように、(+)演算子を列に適用する必要があります。それ以外の場合、Oracleは単純な結合の結果のみを返します。

3つ以上のテーブルのペアの外部結合を実行するクエリでは、1つのテーブルを他の1つのテーブルに対してのみnullで生成されたテーブルにすることができます。このため、AとBの結合条件およびBとCの結合条件のBの列に(+)演算子を適用することはできません。外部結合の構文については、SELECTを参照してください。

http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htmから取得


4

上記の回答にいくつかの矛盾が見られました。Oracle12cで次のことを試しましたが、次のとおりです。

左外部結合

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外部結合

SELECT *
FROM A, B
WHERE B.column(+) = A.column


-2

このスレッドにはいくつかの誤った情報があります。間違った情報をコピーして貼り付けました:

左外部結合

SELECT *
FROM A, B
WHERE A.column = B.column(+)

右外部結合

SELECT *
FROM A, B
WHERE B.column(+) = A.column

上記は間違っています!!!!! 逆転された。私がそれが間違っていると判断した方法は、次の本からです:

Oracle OCP Oracle 9i入門:SQL試験ガイド。表3-1に、これに関する優れた要約があります。古い学校に行って印刷された本を見るまで、変換されたSQLが正しく機能しない理由がわかりませんでした。

これがこの本の要約で、1行ずつコピーされています。

Oracle外部結合構文:

from tab_a a, tab_b b,                                       
where a.col_1 + = b.col_1                                     

ANSI / ISOと同等:

from tab_a a left outer join  
tab_b b on a.col_1 = b.col_1

ここで、上記の投稿の逆であることに注意してください。この本に正誤表がある可能性があると思いますが、このスレッドにあるものよりもこの本を信頼しています。大声で叫ぶための試験ガイドです...


4
これは、Oracle Database 10g SQL(Osborne ORACLE Press Series)第1版(2004年2月20日)からの抜粋である私の回答でリンクしたものと矛盾します。「左外部結合では、外部結合演算子は実際にオンになっています。平等演算子の権利。」これがあなたの例のデモですa.col_1(+) = b.col_1一致の結果は、LEFTJOINではなくRIGHTJOINです。
ワイズガイ2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.