2

次のようなテーブルが与えられた場合

CREATE TABLE [dbo].[Article](
    [Id] [int] NOT NULL,
    [CategoryId] [int] NOT NULL,
    [Text] [nchar](10) NOT NULL)

ユーザーは、データを表示するカテゴリを 1 つ以上選択できます。通常、1 ~ 20 のカテゴリを選択します。それに対応するために、次のようなパラメーター化されたクエリを生成します。

SELECT * FROM Article
WHERE CategoryId IN (@c1, @c2, @c3, @c4, @c5)

ただし、ごくまれに、ユーザーが何百ものカテゴリを正当に選択できる場合があります。これにより、Linq-to-Entities の制限を発見し、カテゴリ コードの範囲を形成することで回避しました。残念ながら、SQL Server に渡すことができるクエリのサイズには制限があるため、これは問題を後押しするだけです。

ハード制限を回避するために、このクエリをリファクタリングしたいと思います。私が最初に考えたのは、要求されたカテゴリを含む一時テーブルを作成し、IN(...)句の代わりにその一時テーブルに対して内部結合を実行することでした。ただし、一時テーブルが非常に遅くなる可能性があることは理解しています。

この問題に対して、よりエレガントでパフォーマンスの高いソリューションはありますか?

4

2 に答える 2

1

編集:

おっとっと。Linqの部分を見逃しました。

試してみる価値のある別の構文を次に示します (文字列の長さの理由ではなく、パフォーマンス上の理由から)

Select * from dbo.Article art where exists ( select null from ( select 0 as MyV union all select 2 as MyV union all select 3 as MyV ) as derived1 where derived1.MyV = art.CategoryId )

...................................

これが私がそれを処理する方法です。

変数テーブルが #temp テーブルに変更されることがあります。2 つの異なるシナリオのパフォーマンスをテストします。

xml を介して多くの値または少ない値を渡すことができます。

DECLARE @input XML = '<root>
  <category myvalue="1" />
  <category myvalue="2" />
  <category myvalue="3" />
</root>'



declare @holder table ( CatID int )
Insert into @holder (CatID)
SELECT
    myvalue = MyXmlTable.value('(@myvalue)', 'int')
FROM
    @input.nodes('/root/category') AS Tbl(MyXmlTable)


select * from @holder    

SELECT * FROM Article art
where exists (select null from @holder hold where hold.CatID = art.CategoryId

ここにもっと大きく書いてください:

http://www.sqlservercentral.com/articles/Stored+Procedures/thezerotonparameterproblem/2283/

于 2013-02-28T22:42:06.247 に答える
1

あなたの最初の直感は正しいですが、一時テーブルの代わりに十分なテーブル値変数を見つけることができるかもしれません。このような場合、パフォーマンスについて心配する必要はありません。それは重要ではありません。必要に応じて、一時テーブルにインデックスを常に作成できますが、それはありそうにありません。CategoryId フィールドにインデックスはありますか?

于 2013-02-28T22:38:40.027 に答える