web-dev-qa-db-ja.com

いつ、またはなぜ、左ではなく右外部結合を使用しますか?

Wikipedia の状態:

「実際には、明示的な右外部結合は、常に左外部結合に置き換えることができ、追加の機能を提供しないため、めったに使用されません。」

誰かがRIGHT表記を使用することを好んだ状況を提供できますか?その理由は?使う理由が思いつきません。私には、それが物事をより明確にすることは決してないでしょう。

編集:私は(+)構文から自分自身を引き離すために新年の決議を行うOracleベテランです。正しくやりたい

50
DCookie

RIGHT OUTER JOINを使用すると考えられる唯一の理由は、SQLをより自己文書化することです。

1対多の関係の従属(多)側にnull行を持つクエリには左結合を使用し、独立側にnull行を生成するクエリには右結合を使用することをお勧めします。

これは、生成されたコードでも、ショップのコーディング要件でFROM句のテーブル宣言の順序が指定されている場合にも発生する可能性があります。

33

これまでright joinを使用したことがなく、実際に必要だとは思っていませんでした。少し不自然に思えます。しかし、考えた結果、1つのテーブルを多くのテーブルの共通部分で外部結合する必要がある場合に、次のようなテーブルができるので、非常に便利です。

enter image description here

そして、このような結果を得たいです:

enter image description here

または、SQL(MS SQL Server)の場合:

declare @temp_a table (id int)
declare @temp_b table (id int)
declare @temp_c table (id int)
declare @temp_d table (id int)

insert into @temp_a
select 1 union all
select 2 union all
select 3 union all
select 4

insert into @temp_b
select 2 union all
select 3 union all
select 5

insert into @temp_c
select 1 union all
select 2 union all
select 4

insert into @temp_d
select id from @temp_a
union
select id from @temp_b
union
select id from @temp_c

select *
from @temp_a as a
    inner join @temp_b as b on b.id = a.id
    inner join @temp_c as c on c.id = a.id
    right outer join @temp_d as d on d.id = a.id

id          id          id          id
----------- ----------- ----------- -----------
NULL        NULL        NULL        1
2           2           2           2
NULL        NULL        NULL        3
NULL        NULL        NULL        4
NULL        NULL        NULL        5

したがって、left joinに切り替えると、結果は同じにはなりません。

select *
from @temp_d as d
    left outer join @temp_a as a on a.id = d.id
    left outer join @temp_b as b on b.id = d.id
    left outer join @temp_c as c on c.id = d.id

id          id          id          id
----------- ----------- ----------- -----------
1           1           NULL        1
2           2           2           2
3           3           3           NULL
4           4           NULL        4
5           NULL        5           NULL

正しい結合なしでこれを行う唯一の方法は、共通のテーブル式またはサブクエリを使用することです

select *
from @temp_d as d
    left outer join (
        select *
        from @temp_a as a
            inner join @temp_b as b on b.id = a.id
            inner join @temp_c as c on c.id = a.id
    ) as q on ...
16
Roman Pekar

B RIGHT JOIN AはA LEFT JOIN Bと同じです

B RIGHT JOIN Aは次のように読み取ります。BON RIGHT、THEN JOINS A.は、Aがデータセットの左側にあることを意味します。 A LEFT JOIN Bと同じ

LEFT JOINをRIGHTに再配置した場合に得られるパフォーマンスはありません。

私がRIGHT JOINを使用する理由を私が考えることができる唯一の理由は、あなたが裏返しに考えたいタイプの人である場合です(select * from detail right join header)。それはリトル・エンディアンのような他のもの、ビッグエンディアンのようなもの、トップダウン設計のようなもの、ボトムアップ設計のようなものです。

もう1つは、別のテーブルを追加したい膨大なクエリが既にある場合で、クエリを並べ替えるのが面倒なので、RIGHT JOINを使用してテーブルを既存のクエリに接続します。

15
Michael Buen

右外部結合について考えるのは、完全結合を修正する場合だけであり、たまたま結果に右側のテーブルのすべてのレコードを含める必要がありました。しかし、私と同じくらい怠惰でも、おそらく私は左の結合を使用するように再配置するほどイライラするでしょう。

Wikipedia のこの例は、私が何を意味するかを示しています。

SELECT *  
FROM   employee 
   FULL OUTER JOIN department 
      ON employee.DepartmentID = department.DepartmentID

WordをFULLからRIGHTに置き換えるだけで、ON句の順序を入れ替えることなく、新しいクエリを作成できます。

7
Bill the Lizard
SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....

Table_cのすべての行が常に選択されていることを確認しながら、最初の2つのテーブルをすばやく/簡単に内部結合し、table_cと結合する方法はありますか?

3
Matt
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col

[空白]を次のものに置き換えます。

LEFT-table2に一致するcolがない場合でもtable1のすべてのレコードが必要な場合(一致するtable2レコードも含まれます)

RIGHT-table1に一致するcolがない場合でもtable2のすべてのレコードが必要な場合(一致するtable1レコードも含まれます)

FULL-table1とtable2のすべてのレコードが必要な場合

誰もが何を話しているのですか?彼らは同じですか?私はそうは思いません。

3

私は本当に正しい結合について多くを考える必要はありませんでしたが、SQLクエリを作成してから20年近く経っていないので、SQLクエリを使用する正当な理由に出くわしました。開発者が組み込みのクエリビルダーをどこで使用したかから、私が推測するそれらの多くを確かに見ました。

問題が発生したときはいつでも、クエリを書き直してそれを排除しました-しばらくクエリにアクセスしなかった場合に、学習したり再学習したりするには、精神的エネルギーが多すぎることがわかっただけです。クエリの目的が失われたり、誤った結果が返されたりすることは珍しいことです。通常、クエリが機能しなかった理由を確認するよう要求する原因となったのは、この誤りです。

考えてみると、ライトジョインを導入すると、途中で満たす必要があるロジックの競合するブランチを検討することができます。追加の要件/条件が導入された場合、これらのブランチの両方がさらに拡張される可能性があり、1つのブランチが誤った結果を引き起こさないようにするために、より複雑にする必要があります。

さらに、適切な結合を導入すると、後でクエリに取り組む経験の浅い他の開発者は、クエリの右結合部分に追加のテーブルをボルトで固定するだけで、それにより、まだ満たす必要がある競合するロジックフローを拡張できます。真ん中;または、場合によっては、ビューのネストを開始します。ビューのネストを開始するのは、元のロジックに触れたくないためです。おそらく、これは、ロジックの原因となったクエリやビジネスルールを理解していない可能性があるためです。

2
mattpm

右結合を使用したのは、2つのデータセットを確認したいときだけで、以前に作成したクエリの左結合または内部結合の結合を特定の順序で既に持っています。この場合、テーブルaではなくテーブルbに含まれているレコードを別のセットのデータとして表示し、別のセットではテーブルbではなくテーブルaにあるレコードを表示したいとします。それでも、時間を節約するためにこれを行う傾向がありますが、コードが複数回実行される場合は変更します。

2
HLGEM

SQLステートメントは、正しいことに加えて、できるだけ読みやすく、表現を簡潔にする必要があります(単一のアトミックアクションを表し、意図しない結果を避けるために、それらを完全に理解する必要があるためです)。右外部結合。

ただし、一方は常に他方に変換することができ、オプティマイザは一方を他方と同様に処理します。

かなり長い間、主要なrdbms製品の少なくとも1つがLEFT OUTER JOINのみをサポートしていました。 (MySQLだと思います。)

2
dkretz

一部のSQLデータベースには、FROM句に出現する順序でテーブルを結合するようにオプティマイザに指示するオプティマイザヒントがあります。 /*+ORDERED */ Oracle。一部の単純な実装では、これが利用可能な唯一の実行プランである場合もあります。

このような場合、FROM句のテーブルの順序は重要なので、RIGHT JOINが役立つかもしれません。

1
Jiri Tousek

この場合、正しい参加がなければ難しいと思います。 Oracleの例。

with a as(
     select 1 id, 'a' name from dual union all
     select 2 id, 'b' name from dual union all
     select 3 id, 'c' name from dual union all
     select 4 id, 'd' name from dual union all
     select 5 id, 'e' name from dual union all
     select 6 id, 'f' name from dual 
), bx as(
   select 1 id, 'fa' f from dual union all
   select 3 id, 'fb' f from dual union all
   select 6 id, 'f' f from dual union all
   select 6 id, 'fc' f from dual 
)
select a.*, b.f, x.f
from a left join bx b on a.id = b.id
right join bx x on a.id = x.id
order by a.id
0
Hong Van Vit