0

ストアド プロシージャでINSERTは、long の結果をUNION一時テーブルに格納する必要があります。このWHERE句は、 にあるすべてのテーブルで同じですSELECT DISTINCT

読みやすくするために簡略化すると、次のようになります。

INSERT INTO #MyTemp
  SELECT col1, col2, col3 FROM tab1 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  SELECT col1, col2, col3 FROM tab2 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  SELECT col1, col2, col3 FROM tab3 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
  .
  .
  .
  SELECT col1, col2, col3 FROM tab20 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) 

TabIds通常は 3 ~ 6 レコードの長さの小さな一時テーブルですが、これはかなり効率が悪いようです。

これを行うより良い方法はありますか?

私の質問を要約すると:

一度だけ実行しSELECT DISTINCT myId FROM TabIdsて、それを一種の配列/リスト/セット(別の一時テーブルではなく)に割り当てて、それをWHERE句で使用する方法はありますか?方法がある場合、そのような方法は本当に重要ですか?小さな (3-6 レコード) 一時テーブル?

4

4 に答える 4

2

私はそれが十分に根拠があるとは思わないので、あなたの要件(「別の一時テーブルではなく」)を無視しています。この解決策でパフォーマンスが向上するかどうかを試してみてください。

SELECT i = myId
  INTO #x 
  FROM dbo.TabIds -- please always use schema prefix
  GROUP BY myId;

CREATE UNIQUE CLUSTERED INDEX x ON #x(i);

INSERT INTO #MyTemp(col1, col2, col3)
SELECT col1, col2, col3
FROM
(
  SELECT col1, col2, col3 FROM dbo.tab1 WHERE EXISTS -- likely better than IN
    (SELECT 1 FROM #x WHERE i = tab1.col1)
  UNION ALL 
  SELECT col1, col2, col3 FROM dbo.tab2 WHERE EXISTS 
    (SELECT 1 FROM #x WHERE i = tab2.col1)
  UNION ALL

  ...

  UNION ALL
  SELECT col1, col2, col3 FROM dbo.tab20 WHERE EXISTS 
    (SELECT 1 FROM #x WHERE i = tab20.col1)
) AS x
GROUP BY col1, col2, col3; -- likely more efficient than `UNION` to remove dupes

もちろん、これは がcol120 個のテーブルすべてでインデックス化されていて、そのインデックスにcol2とが含まれている場合に最適に機能しcol3ます。

私がビューを提案した理由は、それがこのコードの実行を高速化すると考えたからではありません。これを生成するビューを作成してUNIONこのコード (およびこの単調なUNION. これはパフォーマンスのためではなく、利便性のための提案でした。できる場合もありますが、それはビューを避ける危険で非論理的な理由です。

最後に、正規化を強く検討します。そもそも、これらすべてが 1 つのテーブルに収まる可能性があるのに、なぜこれらの 20 の異なるテーブルがあるのでしょうか?

CREATE TABLE dbo.Normal
(
  SourceTableID INT,
  col1 <data type>,
  col2 <data type>,
  col3 <data type>
);

-- indexes / constraints

INSERT dbo.Normal
SELECT 1, col1, col2, col3 FROM dbo.tab1
UNION ALL
SELECT 2, col1, col2, col3 FROM dbo.tab2
UNION ALL

...

UNION ALL
SELECT 20, col1, col2, col3 FROM dbo.tab20;

これで、すべてのクエリがこの新しいテーブルを簡単に参照できるようになります。通常、ソースの 1 つだけを検索する場合 (例: tab5)、インデックス付けまたはパーティション化SourceTableIDが役立ちます。

于 2013-03-06T14:21:25.287 に答える
2

あなたがしていることは、概念的には、1 回限りのデータ読み込みには問題ありません。ただし、これが製品コードのより大きなパターンの一部でないことを願っています。

于 2013-03-04T21:25:38.410 に答える
2

探しているのは、共通テーブル式です。

私の T-SQL は少しさびていますが、CTE を使用すると、クエリは次のようになります。

WITH TabIds_CTE AS (SELECT DISTINCT myId FROM TabIds)
INSERT INTO #MyTemp
SELECT col1, col2, col3 FROM tab1 WHERE col1 IN (SELECT * FROM TabIds_CTE)
UNION ALL ...
于 2013-03-04T21:33:10.543 に答える
1

小さなテーブルには次のほうが適していると思いますが、それでも、生産プロセスでこのようにしておくのは恐ろしい考えです:)

INSERT INTO #MyTemp (col1,col2,col3)
select distinct
    x.col1,x.col2,x.col3 
from (
  SELECT col1, col2, col3 FROM tab1 union all
  SELECT col1, col2, col3 FROM tab2 union all 
  SELECT col1, col2, col3 FROM tab3 union all 
  -- ...
  SELECT col1, col2, col3 FROM tab20
) x
join (
    SELECT DISTINCT myId FROM TabIds
) y
on x.col1=y.myid
于 2013-03-05T16:32:22.067 に答える