web-dev-qa-db-ja.com

LEFT JOINよりもRIGHT JOINを選択する理由

私が正しく理解していれば、すべてのRIGHT JOIN

SELECT Persons.*, Orders.*
FROM Orders
RIGHT JOIN Persons ON Orders.PersonID = Persons.ID

LEFT JOINとして表すことができます:

SELECT Persons.*, Orders.*
FROM Persons
LEFT JOIN Orders ON Persons.ID = Orders.PersonID

私の個人的な見解では、ステートメントの意図は次のとおりです。

  • 最初にPersonsを取得します
  • 次に、Personsを一致させるために、必要に応じてOrdersを展開/繰り返します

逆順のPersons LEFT JOIN OrdersよりもOrders RIGHT JOIN Personsの順で表現するほうがよい(結果としてRIGHT JOINを使用することはない)。

RIGHT JOINが優先される状況はありますか?または、RIGHT JOINLEFT JOINができないことを実行できるユースケースはありますか?

18
Zev Spitz

それは、あなたが満たそうとしている要件に依存します。

"gimme all person and their following order"that "I want all all order with their their person"、特にis nullを使用して対応する一致のない行を取得する場合。これが、「ドミナントテーブル」と呼ばれるものです。これは、結合の反対側に対応する行がない場合でも、行をフェッチするテーブルです。

この画像を見ると、同じではないことがわかります。

enter image description here

画像のソースはこの優れた記事です

しかし、どちらの要件も、結合内のテーブルの順序を逆にするだけで満たすことができるという点で正しいです。

しかし、左から右に書くことに慣れている西洋人にとっては、右結合よりも左結合を使用する方がより自然になると思いますselected列と同じ方向または同じ順序の結合。

それで、正しい結合を好む理由として考えられるのは、です。文化では、アラビア語やヘブライ語の書記体系のように、右から左に書いて、そのように考える傾向があるためです。おそらくあなたの脳のテキスト情報は右から左に流れます。

一部の言語学者は、あなたの言語があなたの考え方に影響を与えると考えています: https://www.Edge.org/conversation/lera_boroditsky-how-does-our-language-shape-the-way-we-think

11

左結合では実行できない右結合で実行できる(私が知っている)ものはありません。ただし、左結合を使用した構文が見にくい場合があります。次のテーブルがあるとします。

Persons
ID | Name

Orders
ID | CustomerId | other unimportant stuff

SpecialOrderDetails
ID | OrderId | other stuff

データベース内のすべての人と特別注文の詳細を含むすべての注文のリストを取得する必要があるとします(すべての注文に特別注文の詳細があるとは限りません)。したがって、通常は、人からオーダーへの左結合を行います。ただし、特別注文の詳細に参加する必要があります。そこで内部結合を使用すると、人から注文への左結合が内部結合になります。 IE:これはあなたがやりたいことですが機能しません(特別な順序を持っていない人は除外されます):

select p.*, o.*, d.*
from Persons p
left join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

したがって、次のように書き直すことができます。

--get all the people without a special order
select p.*, NULL, NULL, ... --NULLs placeholders for all the fields from OrderDetails and SpecialOrderDetails
from Persons p
left join Orders o on o.CustomerId = p.Id
left join SpecialOrderDetails d on d.OrderId = o.Id
where o.Id is null 

union

--get all the people with a special order
select p.*, o.*, d.*
from Persons p
inner join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

明確ではありませんが(コメントがないと仮定して)、それでうまくいきます。これが1回限りのものではない場合(つまり、誰かが戻ってきて、いつかメンテナンスしなければならないようなもの)、正しい結合を使用すると、意図が何であるかが明確になる場合があります。

select p.*, o.*, d.*
from Orders o
inner join SpecialOrderDetails d on d.OrderId = o.Id
right join Persons p on p.Id = o.CustomerId

これはもう少し簡潔で明確です(しかし、それを読んでいる人が正しい結合を理解している場合のみ)。これは左結合で記述できますが、ネスト結合が必要であることに注意してください(これはおそらく右結合よりも馴染みのない人です)。

select p.*, o.*, d.*
from Persons p
left join Orders o 
    inner join SpecialOrderDetails d on d.OrderId = o.Id
on o.CustomerId = p.Id

この時点で、それは最も明確で、ほとんどの人が理解することの選択です(ネストされた結合と呼ばれていたことを知らなかった場合、その構文をグーグルする方法を知っていますか?)。

つまり、厳密にはneed結合ではありませんが、読みやすくなる場合があります。

3
Becuzz