「レガシー」から現在へのクロスオーバーポイントで、計算された値の複雑なセットを返す必要があるシナリオに遭遇しました。
長い話を短くするために、私はこのようなものを持っています...
with someofit as
(
select id, col1, col2, col3 from table1
)
select someofit.*,
case when id < @lastLegacyId then
(select ... from table2 where something = id) as 'bla'
,(select ... from table2 where something = id) as 'foo'
,(select ... from table2 where something = id) as 'bar'
else
(select ... from table3 where something = id) as 'bla'
,(select ... from table3 where something = id) as 'foo'
,(select ... from table3 where something = id) as 'bar'
end
from someofit
ここに問題はありません...サブ選択ごとにそのケースチェックを常に実行したくはありませんが、同時にその条件が適用される場合は、関連するケースブロック内のすべての選択が必要です。
これを行うためのよりスマートな方法はありますか?
適切なオブジェクト指向言語を使用している場合は、次のようなものを使用します...
var common = GetCommonSuff()
foreach (object item in common)
{
if(item.id <= lastLegacyId)
{
AppendLegacyValuesTo(item);
}
else
{
AppendCurrentValuesTo(item);
}
}
最初は、すべてユニオンを使用して2つの完全な選択を実行しようとしましたが、効率/評価する行数のため、これはあまりうまく機能しません。
サブセレクションは、テーブル2または3のいずれかでIDが一致する以外の条件が満たされているが、それらのテーブルに数百万の行が含まれている可能性がある合計行数を探しています。
cteは2つの理由で使用されます...
まず、テーブル1から行のみを取得します。興味があるので、すぐに、それぞれの場合にサブ選択の一部のみを実行します。
次に、テーブル1の1回のルックアップで一般的なものを返します。
何か案は?
編集1:
状況へのいくつかのコンテキスト...
「imports」というテーブル(上記の表1)があります。これは、ファイル(csvなど)からデータを取得し、レコードをデータベースにプルするインポートジョブを表しています。
次に、「ステップ」と呼ばれるテーブルがあります。これは、実行する処理/クリーニングルールを表し、各レコードには、sproc名とルールに関するその他の情報が含まれています。
次に、特定のインポート「ImportSteps」のルールを表す結合テーブルがあります(上記の表2-現在のデータの場合)。これには、「rowsaffected」列とインポートIDが含まれます。
したがって、現在のジョブの場合、私のSQLは非常に単純です...
importsjoinimportstepsから123456を選択します
古いレガシーのものについては、テーブル3を確認する必要があります...テーブル3は保持テーブルであり、これまでにインポートされたすべてのレコードが含まれ、各行にはインポートIDがあり、各行にはキー値が含まれます。
ステップIDがyであるインポートIDxのテーブル2で影響を受ける新しいデータ行で、私の値が返されます。
レガシーデータでは、colz=何かを保持している行を数える必要があります
約20のインポートに関するデータが必要であり、このデータはmvc Webアプリの「datagrid」にバインドされています(違いがある場合)
私が使用するcteは、いくつかのパラメーターを介して、それらのパラメーターが開始レコードと終了レコード(インポートIDの順序)を表す「現在関心のある20im」を決定します。
私の最大の問題は、テーブルを保持することです...それは巨大です..個々のジョブはそれ自体で500k以上のレコードを含むことが知られており、このテーブルは何年ものインポートされた行を保持するので、そのテーブルでのルックアップをできるだけ速くする必要がありますできるだけ少なくします。
編集2:
実際の解決策(suedoコードのみ)..。
-- declare and populate the subset to reduce reads on the big holding table
declare table @holding ( ... )
insert into @holding
select .. from holding
select
... common stuff from inner select in "from" below
... bunch of ...
case when id < @legacy then (select getNewValue(id, stepid))
else (select x from @holding where id = ID and ... ) end as 'bla'
from
(
select ROW_NUMBER() over (order by importid desc) as 'RowNum'
, ...
) as I
-- this bit handles the paging
where RowNum >= @StartIndex
and RowNum < @EndIndex
私はまだそれをもっときれいにすることができると確信していますが、請求書の解決策のように見えた私の元のクエリは実行時間で約45秒でした、これは約7です