7

私は3つのテーブルを持っています:

  • 注文
    • OrderId、int PK
    • CustomerId、Customer への int FK、NULL を許可


  • お客様
    • CustomerId、int PK
    • CompanyId、Company への int FK、NULL は許可されません


  • 企業
    • CompanyId、int PK
    • 名前、nvarchar(50)

顧客がいるかどうかに関係なく、すべての注文を選択し、顧客がいる場合は顧客の会社名も選択したいと考えています。

このクエリを使用すると...

SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM   Orders
       LEFT OUTER JOIN Customers
           ON Orders.CustomerId = Customers.CustomerId
       INNER JOIN Companies
           OM Customers.CompanyId = Companies.CompanyId

...顧客がいる注文のみを返します。に置き換えるINNER JOINLEFT OUTER JOIN...

SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM   Orders
       LEFT OUTER JOIN Customers
           ON Orders.CustomerId = Customers.CustomerId
       LEFT OUTER JOIN Companies
           OM Customers.CompanyId = Companies.CompanyId

Customers...動作しますが、との関係が必要なため、これが必要な理由がわかりませんCompanies: 顧客には会社が必要です。

同様に機能する代替アプローチは次のようです。

SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM   Companies
       INNER JOIN Customers
           ON Companies.CompanyId = Customers.CompanyId
       RIGHT OUTER JOIN Orders
           OM Customers.CustomerId Orders.CustomerId

このクエリには、予想される内部結合と外部結合の数がありますが、問題は、注文が選択の「ルート」であり、選択の「ルート」ではない注文のクエリとしてクエリを念頭に置いているため、読みにくいことです。会社。また、 の使用法はRIGHT OUTER JOIN私にはあまりなじみがありません。

最後のクエリは、SQL Server Reporting Services レポートのデザイナーによって生成されたクエリの一部です。非常に混雑していて、多くの変更後にクエリを維持するのに問題があり、将来さらに多くの変更が予想されるため、デザイナー画面なしでクエリを手動で記述しようとしています。だから、どうにかしてクエリに読み取り可能な構造を与えたいと思います。

質問:

  1. クエリ 1 が期待どおりに機能しないのはなぜですか?
  2. クエリ 2 は、2 つの LEFT OTHER JOINS を使用していますが (またはそのため?)、正しい解決策ですか?
  3. クエリ 3 は正しい解決策ですか?
  4. クエリを記述するより良い方法はありますか?
  5. 多くの外部結合と内部結合を含むクエリを読みやすい方法で作成するための一般的な経験則と実践方法はありますか?
4

5 に答える 5

12

意味的には、結合はfrom句に現れる順序で処理されます。(SQL の最適化により、実際にはこの順序で実行されない場合がありますが、結果セットを定義するには順序が重要です。)

だから、あなたがするとき:

from orders left outer join customers inner join companies

onこの目的のために気を散らす条項は省略しています。)

SQL は次のように解釈されます。

from (orders left outer join customers) inner join companies

を実行しているinner joinため、値は両側に表示される必要があります。あなたの場合、これは の効果を元に戻しますleft outer join

あなたがしたい:

from orders left outer join (customers inner join companies)

ここにいくつかの解決策があります。

私の推奨する解決策はleft outer join、すべての結合に使用することです。実際、読みやすさと保守性のために、私が作成するほとんどすべてのクエリは、テーブルのみleft outer joinまたは[inner] joinテーブルを接続することになります。クエリを一貫した形式で記述できる場合、結合のセマンティクスを理解するためにクエリを解析する必要はありません。

別の解決策は、括弧を使用することです。

from orders left outer join (customers inner join companies)

別の解決策はサブクエリです。

from orders left outer join (select . . . from customers inner join companies) cc
于 2013-05-08T14:21:00.787 に答える
2

クエリ 1 には Company に INNER JOIN があります。つまり、 Order には有効な Customer(CompanyID) が必要です。INNER JOIN を使用する場合は、次のようになります。

SELECT Orders.OrderId, a.CustomerId, a.Name
FROM   Orders
LEFT JOIN (
  SELECT Customers.CustomerId, Companies.Name
  FROM Customers
  INNER JOIN Companies
           OM Customers.CompanyId = Companies.CompanyId
) a 
  ON  Orders.CustomerId = a.CustomerId
于 2013-05-08T14:22:09.553 に答える