0

私の仕事は、SQL サーバー (MSSQL2005) を多用する 1 つのアプリケーションを保守することです。
これまで、中間サーバーは TSQL コードを XML に格納し、ストアド プロシージャを使用せずに動的 TSQL クエリを送信していました。
これらの XML クエリを変更できるので、ほとんどのクエリをストアド プロシージャに移行したいと考えています。
質問は次のとおりです。

私のクエリのほとんどは、1 つのテーブルに対して同じ Where 条件を持っています

サンプル:

Select 
   .....
from ....
where ....
and (a.vrsta_id = @vrsta_id  or @vrsta_id = 0)
and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0)
and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0)
and (
 (a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina))
        group by art_id
        having count(art_id)= @podosobina_count ))
     or ('0' = @podosobina)
 )

他のテーブルにも同じ場所条件があります。

コードをどのように整理すればよいですか?
適切な方法は何ですか?
すべてのクエリで使用するテーブル値関数を作成する
か、#Temp テーブルを使用して、プロシージャを実行するたびにクエリを単純な内部結合にする必要がありますか? または、テーブル値関数によってファイルされた #temp を使用しますか?
または、すべてのクエリにこの大きな where 句を残して、インデックスが機能することを期待します。
またはWITH(ステートメント)を使用します

4

3 に答える 3

2

ここでは、2つの異なる機能上の懸念があります。1つのテーブルからの値の選択と、返される列またはそのデータに結合される他のテーブルの選択です。1つのテーブルでフィルタリングするアイテムの数が多い場合は、選択した値のPKをミドルテーブルまたはワークテーブルに格納する傾向があります。永続的なテーブルの場合は、SessionIdなどでさまざまな検索を分離するか、フィルタリングルーチンから選択ルーチンに渡すランダムな値で検索結果の各セットを分離することができます。

動的SQLでフィルタリングルーチンを維持できなかった理由はありません。ただし、T-SQLで動的SQLを実行しようとはしません。T-SQLは文字列操作にひどいです。中間層から動的にクエリを構築すると、効果的に渡されない要素をWhere句から除外することができます。たとえば、を持っている代わりに、が実際にゼロであるand (a.vrsta_id = @vrsta_id or @vrsta_id = 0)場合はこの行を完全に除外するか、がゼロでない場合は単純に除外することができます。一般に、このタイプのクエリは、一連のORよりもパフォーマンスが高くなります。@vrsta_ida.vrsta_id = @vrsta_id@vrsta_id

作業テーブルを作成すると、選択するクエリは次のようになります。

Select..
From WorkTable As W
    Join ...

Where SetId = 12345
    And ( OtherTable.Col = ....

この場合、SetIdは、フィルタリングルーチンから作成されたアイテムのセットを表します。

于 2010-06-16T15:05:59.340 に答える
2

単一のクエリでこのような複雑な検索を行うことは、あまり良い考えではないことに気付きました。

入力条件値に基づいてSQL depedingを構築することを好みます。これにより、rsql サーバーが各検索に対してより適切な実行計画を作成しやすくなります。このようにして、クエリの実行計画が最適化されていないことは間違いありません。

これには動的SQLが含まれることを認識しているため、通常の警告が適用されます。

于 2010-06-16T14:31:16.680 に答える
1

パラメータを受け取り、一致するa.id値のテーブルを返すテーブル値関数を作成できます。次に、その関数を各ストアドプロシージャのクエリに内部結合できます。例えば:

create function dbo.GetMatches
(
@vrsta_id int,
@podvrsta_id int,
@podgrupa2_id int,
@podosobina_count int
)
returns table
as
return
Select 
a.id
from a
where
(a.vrsta_id = @vrsta_id  or @vrsta_id = 0)
and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0)
and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0)
and (
(a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina))
group by art_id
having count(art_id)= @podosobina_count ))
or ('0' = @podosobina)
)

次に、この例のクエリでは...

select
*
from
a
inner join dbo.GetMatches(1,2,3,4) matches
on a.id = matches.id
inner join b on a.bID = b.bID -- example other table

このようなwhereステートメントでその関数を使用することもできます...

where
    a.id in (select id from dbo.GetMatches(1,2,3,4))
于 2010-06-16T15:25:06.207 に答える