2012-01-10 15 views
2

T-SQLクエリでテーブルへの条件付き結合を作成したいとします。この例で使用されるテーブル(唯一つの追加のテーブル製品のリストを有する)ノースウィンドデータベースから条件付きでテーブルを結合する

表製品および表カテゴリー多対多の関係を有している、したがってテーブル製品のリストは、画像に入ってきます。

私は特定のカテゴリに該当する製品ごとにテーブルたOrderDetailsの数量の列の合計を必要とします。だから私は以下のようなクエリを持っています

Select p.ProductName, Sum(od.Quantity) As Qty 
From Products p 
    Join OrderDetails od On od.ProductID = p.ProductID 
    Join ProductCategories pc On pc.ProductID = p.ProductID 
     And pc.CategoryID = @CategoryID 
Group By p.ProductName 

@CategoryIDはオプションのパラメータです。場合には、それが供給されていないですので、 必要とされることはありません、テーブルの製品のリストに参加して、クエリは、私は全体のクエリを繰り返すことなく、これを達成したいもの

Select p.ProductName, Sum(od.Quantity) As Qty 
From Products p 
    Join OrderDetails od On od.ProductID = p.ProductID 
Group By p.ProductName 

の下のようになります。もし条件

(以下など)
If @CategoryID Is Null 
    Select p.ProductName, Sum(od.Quantity) As Qty 
    From Products p 
     Join OrderDetails od On od.ProductID = p.ProductID 
    Group By p.ProductName 
Else 
    Select p.ProductName, Sum(od.Quantity) As Qty 
    From Products p 
     Join OrderDetails od On od.ProductID = p.ProductID 
     Join ProductCategories pc On pc.ProductID = p.ProductID 
      And pc.CategoryID = @CategoryID 
    Group By p.ProductName 

は、これは製品のリストのような多くの他のテーブルと条件を持つクエリの簡易版です。複数の複数のIf条件とクエリの繰り返しが必要になります。私は動的にクエリを生成しようとしました。それは動作しますが、クエリは全く読めません。

すべてのソリューションはありますか? ありがとうございます。私は、「これはそれをカットするかどうか、私は知りませんが、MySQLにあなたがして()はまだ残っているが、ちょうど場合

Select p.ProductName, Sum(od.Quantity) As Qty 
From Products p 
    Join OrderDetails od On od.ProductID = p.ProductID 
    Join ProductCategories pc On pc.ProductID = p.ProductID 
     And pc.CategoryID = if(@CategoryID is null , pc.CategoryID, @CategoryId) 
Group By p.ProductName 

はいのような何かができるT-SQLに精通していないよ

答えて

2

あなたが適切にパラメータ化クエリを使用します場合は、これを試してみてください - そこには、パフォーマンスに影響しないであろうが、ゲインことがあります複数の行があることができれば、あなたのクエリで

Select p.ProductName, Sum(od.Quantity) As Qty 
From Products p 
    Join OrderDetails od On od.ProductID = p.ProductID 
WHERE @CategoryID IS NULL OR EXISTS (SELECT * FROM ProductCategories WHERE CategoryID = @CategoryID AND ProductID = p.ProductID) 
Group By p.ProductName 

実際

ProductCategoriesOrderDetailsに1行 - あなたのSUMにod.Quantityの重複を取得 - これは意図した動作ですか?

+0

重複のod.Quantityは、私が避けようとしていることであり、@ CategoryIDが指定されていない場合、ProductCategoriesテーブルに参加したくない理由があります。 – Romeo

+0

ありがとうございます。 – Romeo

0

1つのクエリ "、それがあなたが探しているものならば。

同時に、1つのクエリを動的に生成できたとします。そうであれば、読みやすさが問題の多くですか?あなたの生成されたクエリが、私が上に示唆したものよりもパフォーマンスが良いなら、私はそのことに行きます。生成されます。結果を手作業で微調整したり読んだりすることができます。

+0

正しい構文 「とpc.CategoryID = CASE WHEN "(@区分が区分、@、pc.CategoryID nullの)場合とpc.CategoryID =" 私はあなたがこの と、ここでやろうとしているか知っています@区分がnullの場合、それは製品のリストは、単一の製品のために複数のレコードを含めることができるので、私は(行を複製し得るでしょう、 しかし区分エンド」@エルスpc.CategoryIDです。 – Romeo

0

私はあなたがやっている暗黙的な内部結合とテーブルを結合することができると信じています。

内部結合では、ソース表のキーと宛先表のキーの各インスタンスが一致します。

先テーブルにマッチの各インスタンスは マッチタイプを表示する行のセットを生成します。外付

は、他のテーブルに一致する行が存在しない場合でも、それは、ソース行を表示する参加します。もしそれが本質的にインナージョイントと同じことをするならば、あなたはマッチの各インスタンスのために行を返すでしょう。したがって、利用可能なときに必要なデータを取得し、利用できないデータを取得しないようにします。

例私はProductIDCategoryIDCategoryName

CategoryIDCategoriesテーブルで ProductIDProductName ProductAndCategoryテーブルでシンプルな Productテーブルを持っている

select * from Products 

    Left join ProductAndCategory on ProductAndCategory.ProductID = Products.ProductID 
    left join Categories on Categories.CategoryID = ProductAndCategory.CategoryID 

としてこれを取ります

カテゴリを結合したカテゴリを持つ行とカテゴリを持たない行が表示されます。存在しない。

+0

左は私の問題を解決しない参加。 – Romeo

関連する問題