1

次の2つのSQLクエリは同じ結果を返します。

    SELECT * FROM Table1
    WHERE Table1.Value1 = 'something' OR Table1.Value2 IN (SELECT Value2 FROM Table2)

    SELECT * FROM Table1
    LEFT JOIN Table2 
    ON Table1.Value2 = Table2.Value2
    WHERE (Table1.Value1 = 'something' OR Table2.Value2 IS NOT NULL)

同様に、これら2つのクエリは同じ結果を返します。

    SELECT * FROM Table1
    WHERE Table1.Value1 = 'something' AND Table1.Value2 NOT IN (SELECT Value2 FROM Table2)

    SELECT * FROM Table1
    LEFT JOIN Table2
    ON Table1.Value2 = Table2.Value2
    WHERE Table1.Value1 = 'something' AND Table2.Value2 IS NULL

個人的には、「IN」または「NOT IN」を使用するオプションを読む方が簡単だと思います(特に、実際のクエリにはすでに結合の山が含まれているため)。ただし、Table2の値の数が大きくなると(現在は3つの結果しか返されない)、このクエリは非効率になりますか?それとも、クエリオプティマイザはそれを理解し、舞台裏で結合に変えますか?SQLServer2012を使用しています。

4

2 に答える 2

1

最初のものは次のように優れています。

SELECT <cols> 
  FROM dbo.Table1
  WHERE Value1 = 'something' 
  OR EXISTS (SELECT 1 FROM dbo.Table2 WHERE Value2 = Table1.Value2);

パフォーマンスの問題はありますが、Value2 が両方の場所でインデックス化されており、* を使用してスキャンまたはルックアップを強制するのではなく、実際に必要な列のみを選択すると仮定すると、OR になります。Value1 が適切にインデックス化されている場合は、少なくともパフォーマンスの違いをテストするために、この代替案を検討できます (行が 3 つしかない場合は、時間を測定するだけでなく、計画を確認する必要があります)。

SELECT <cols>
  FROM dbo.Table1 
  WHERE Value1 = 'something'
UNION ALL
SELECT <cols>
  FROM dbo.Table1
  WHERE Value1 <> 'something'
  AND EXISTS (SELECT 1 FROM dbo.Table2 WHERE Value2 = Table1.Value2);

NOT IN クエリの場合、これはより信頼性が高く、少なくとも提供した 2 つのオプションと同じくらい効率的です。

SELECT <cols>
  FROM dbo.Table1
  WHERE Value1 = 'something' 
  AND NOT EXISTS (SELECT 1 FROM dbo.Table2 WHERE Value2 = Table1.Value2);

ここではインデックス作成が重要になりますが、NOT IN と LEFT OUTER JOIN を使用すると問題が発生する可能性があることを理解することが重要です。次の記事を参照してください。

http://www.sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join

于 2013-01-15T19:07:19.030 に答える
1
  • これら 2 つのクエリは同等ではありません。IN (または NOT IN) を使用すると、Table1 の各行に対して 0 または 1 つの結果行が取得されます。join を使用すると、各行は 0 回、1 回、または複数回表示されます。したがって、「2 つの SQL クエリが同じ結果を返す」というのは、特定のデータが原因です。または、Table2 は Value2 に一意のインデックス/PK を持っています

  • UNION を次のように使用する

SELECT ... WHERE Table1.Value1 = 'something'
UNION (ALL)
SELECT ... WHERE Table1.Value2 = Table2.Value2

UNION は重複を削除し (これは価値がある場合があります)、UNION ALL は両方の基準に一致する場合、一部の結果行を 2 倍にする可能性があるため、異なる結果が得られる場合もあります。

  • 最初のクエリで IN() の代わりに EXISTS() を使用する場合... SQL オプティマイザーはこれらの操作が等しいことを認識し、同じ最適な方法を選択するため、ほとんどの場合、同一の実行計画が得られます。

  • ステートメントでサブクエリを使用する場合でも、SQL オプティマイザーは、サブクエリを使用しない方法で計画を再構築する場合があります。つまり、異なる方法で記述された 2 つの同等のクエリは、ほとんどの場合、同じプランに最適化されます。

  • SQL が最適化を完全に完了するのに十分な時間がなく、停止したところで停止する可能性があるため、機能しない可能性がある非常に複雑なクエリの場合。この場合、そのような異なるが類似したクエリは、異なる結果になる可能性があります。試してテストする必要があります。

計画とパフォーマンスは、データ、パラメーターの種類 (定数、変数、計算値)、統計、インデックスなどに依存します。また、これらの条件の組み合わせによっては、クエリ 1 がクエリ 2 よりも最適であり、その逆も同様です。その他。

正しい答えを得るには、実行計画を分析して比較する必要があります

于 2013-01-15T20:43:48.453 に答える