これはハッシュされ、再ハッシュされています。 コメントで指摘したヒント 上記のリンクと説明 @xQbert は、リクエストに応じて、サブクエリを使用した COALESCE と ISNULL の説明です。次の 2 つのクエリを考えてみましょう。結果は同じです:
SELECT COALESCE((SELECT TOP (1) name FROM sys.objects), N'foo');
SELECT ISNULL((SELECT TOP (1) name FROM sys.objects), N'foo');
( /dev/null/ への ORDER BY なしで TOP を使用することについてのコメントありがとう。)
COALESCE の場合、ロジックは実際には次のように展開されます。
SELECT CASE WHEN (SELECT TOP (1) ...) IS NULL
THEN (SELECT TOP (1) ...)
ELSE N'foo'
END
ISNULL では、これは起こりません。サブクエリが 1 回だけ評価されるようにする内部最適化があります。 Microsoft 以外の誰かがこの最適化がどのように機能するかを正確に知っているかどうかはわかりませんが、計画を比較すればわかります。 COALESCE バージョンの計画は次のとおりです:
そして、ISNULL バージョンの計画は次のとおりです - それがどれほど単純であるかに注目してください (そして、スキャンは 1 回だけ行われることに注意してください):
COALESCE の場合、スキャンは 2 回行われます。結果が得られなくても、サブクエリが 2 回評価されることを意味します。サブクエリが 0 行を生成するように WHERE 句を追加すると、同様の相違が見られます。計画の形状は変わる可能性がありますが、COALESCE ケースの二重のシーク + ルックアップまたはスキャンが引き続き表示されます。少し異なる例を次に示します:
SELECT COALESCE((SELECT TOP (1) name FROM sys.objects
WHERE name = N'no way this exists'), N'foo');
SELECT ISNULL((SELECT TOP (1) name FROM sys.objects
WHERE name = N'no way this exists'), N'foo');
今回の COALESCE バージョンの計画 - ここでも、逐語的に繰り返されるサブクエリを表すブランチ全体を見ることができます:
また、ISNULL を使用して、作業の約半分を行う、はるかに単純な計画:
この質問は、dba.se でさらに議論することもできます:
私の提案は次のとおりです (そして、ヒントと上記の質問で私の理由を確認できます):信頼しますが、検証します。私は常に COALESCE を使用します (これは ANSI 標準であり、3 つ以上の引数をサポートしており、データ型の優先順位でそれほど奇妙なことをしないためです) 例外 式の 1 つとしてサブクエリを使用していることはわかっています (このような理論的な作業以外ではこれまでに行ったことを思い出せません)。または、実際のパフォーマンスの問題が発生していて、COALESCE と ISNULL に何かがあるかどうかを比較したいだけです。実質的なパフォーマンスの違い (サブクエリのケース以外では、まだ見つけていません)。ほとんどの場合、同じようなデータ型の引数で COALESCE を使用しているため、過去に述べたことを振り返る以外にテストを行う必要はほとんどありません (私は xQbertが指摘したaspfaq記事 、7 年前)。