これはハッシュ化され、再ハッシュ化されています。上記のコメントとリンクと説明で指摘したヒントに加えて、リクエストにより、サブクエリを使用した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');
(ORDERBYなしでTOPを使用することについてのコメント/dev / null /に感謝します。)
COALESCEの場合、ロジックは実際には次のように拡張されます。
SELECT CASE WHEN (SELECT TOP (1) ...) IS NULL
THEN (SELECT TOP (1) ...)
ELSE N'foo'
END
ISNULLでは、これは発生しません。サブクエリが1回だけ評価されるようにする内部最適化があります。マイクロソフト以外の誰かがこの最適化がどのように機能するかを正確に知っているかどうかはわかりませんが、計画を比較すればこれは可能です。COALESCEバージョンの計画は次のとおりです。
そして、これがISNULLバージョンの計画です-それがどれほど単純であるかに注意してください(そしてスキャンは一度だけ行われることに注意してください):
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年前)。