web-dev-qa-db-ja.com

ISNULLを使用する場合と特定の条件をチェックするためにCOALESCEを使用する場合

複数のパラメーターをCOALESCEに渡すことができることは知っていますが、1つの式だけが存在しないかどうかを確認したい場合は、デフォルトを使用するか、ISNULL代わりに?

2つの間にパフォーマンスの向上はありますか?

69
JBone

Microsoft Connectで報告されたこの問題 は、COALESCEISNULLの違いを明らかにします。

処理の初期段階では、COALESCE( expression1, expression2 )CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END。 [この例]:

COALESCE ( ( SELECT Nullable
             FROM Demo
             WHERE SomeCol = 1 ), 1 )

生成します:

SELECT CASE
          WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL
          THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1)
          ELSE 1
       END

クエリ処理の後の段階では、2つのサブクエリが元々同じ式であることを理解していないため、サブクエリを2回実行します...

回避策の1つとして、COALESCEISNULLに変更することをお勧めしますが、後者はサブクエリを複製しないためです。

55
onedaywhen

私はそうは思いませんが、COALESCEはSQL '92標準にあり、より多くの異なるデータベースでサポートされています。移植性を重視する場合、ISNULLを使用しないでください。

24
GolezTrol

[〜#〜] coalesce [〜#〜] では、複数の式を使用できます。ここで [〜#〜] isnull [〜#〜] でのみチェックできます一つの表現

COALESCE ( expression [ ,...n ] ) 

ISNULL ( check_expression , replacement_value )
11
otti

言及する価値があるのは、2つの間の型処理も違いを生む可能性があることです( この関連する回答項目(2) を参照)。

クエリがnull比較を記述するためにショートカットを使用しようとするとします。

select * from SomeTable
 where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);

とは異なります

select * from SomeTable
 where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);

前者の場合、IsNull()は型をビットに強制するため(-1はtrueに変換されます)、後者の場合は両方をintにプロモートします。

with input as 
(
  select convert(bit, 1) as BitOn,      
         convert(bit, 0) as BitOff,
         convert(bit, null) as BitNull
)
select BitOn, 
       BitOff,
       BitNull,
       IsNull(BitOn, -1) IsNullBitOn,         -- true
       IsNull(BitOff, -1) IsNullBitOff,       -- false
       IsNull(BitNull, -1) IsNullBitNull,     -- true, converts the -1 to bit
       coalesce(BitOn, -1) CoalesceBitOn,     -- 1
       coalesce(BitOff, -1) CoalesceBitOff,   -- 0       
       coalesce(BitNull, -1) CoalesceBitNull  -- -1
  from input;

質問自体にも同様のコメント/リンク(@Martin Smith)があります。

7
crokusek

明示的に示されていない主要なことの1つは、ISNULLの出力タイプが最初の式に似ていますが、COALESCEを使用すると、優先順位の最も高い値のデータタイプを返します。

DECLARE @X VARCHAR(3) = NULL
DECLARE @Y VARCHAR(10) = '123456789'
/* The datatype returned is similar to X, or the first expression*/
SELECT ISNULL(@X, @Y) ---> Output is '123'
/* The datatype returned is similar to Y, or to the value of highest precedence*/
SELECT COALESCE(@X, @Y) ---> Output is '123456789'
5
BICube

この説明は、合体とisnullについて明確に説明しています。

SQLのCOALESCE関数は、引数の中で最初の非NULL式を返します。 COALESCEの構文は次のとおりです。

 COALESCE ("expression 1", "expressions 2", ...)

次のCASEステートメントと同じです。

SELECT CASE ("column_name")
  WHEN "expression 1 is not NULL" THEN "expression 1"
  WHEN "expression 2 is not NULL" THEN "expression 2"
  ...
  [ELSE "NULL"]
  END
FROM "table_name";

SQL Serverでは、ISNULL()関数を使用して、NULL値を別の値に置き換えます。

select CountryName = ISNULL("columnname", 'INDIA') from Countries

Coalesceは、isnull()を使用してnull値を目的の値に置き換える最初の非null式を返します。

COALESCEはANSI標準の一部であり、ほぼすべてのデータベースで利用できます。

iSNULL v COALESCEを決定するときは、パラメーターをオフにする必要があります。

  1. COALESCEは、データ型の優先順位に基づいて出力のタイプを決定します。ISNULLと同様に、データ型はデータ型の優先順位の影響を受けません。
  2. 次のSQL文を検討してください

    DECLARE @c5 VARCHAR(5);
    SELECT 'COALESCE', COALESCE(@c5, 'longer name')
    UNION ALL
    SELECT 'ISNULL',   ISNULL(@c5,   'longer name');
    

結果:

COALESCE longer name
ISNULL   longe

これは、ISNULLが最初の引数のデータ型を受け取り、COALESCEがすべての要素を検査し、最適なもの(この場合はVARCHAR(11))を選択するために発生します

COALESCEとISNULLの決定に関する詳細な説明については、これを確認してください: https://www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql- server /

2

Null条件が1つしかない場合、ISNULLのオーバーヘッドは小さくなります。ただし、おそらく違いはごくわずかです。

2
James Johnson

NULLCOALESCEは、常に交換できるとは限りません。どちらを使用するほうがよいかを知るために、両者の違いを知るに値します。

enter image description here

上記の表は、Itzik Ben-Ganが書いた_Exam Ref 70-761 Querying Data with Transact-SQL_本のISNULLCOALESCEの比較です。


  1. サポートされているパラメーターの数-ISNULLを使用する場合のCOALESCE対_2_の_>2_
  2. ISNULLは独自のT-SQL機能であり、COALESCEはISO/ANSI SQL標準です
  3. 結果のデータ型は重要です。上記の表の注意事項を読んだ後、次のケースを確認してください。

    _DECLARE @x VARCHAR(3)  = NULL
           ,@y VARCHAR(10) = '1234567890';
    
    SELECT ISNULL(@x, @y) AS [ISNULL], COALESCE(@x, @y) AS [COALESCE];
    _

    enter image description here

    ISNULLは、NULLリテラルではないため、最初の引数のデータ型を取得しています。これはVARCHAR(3)であり、結果であり、2番目の引数データはそれに一致するようにカットされます。 COALESCEでは、最高の優先順位が使用される場合のデータ型。

    _DECLARE @x VARCHAR(8)  = '123x5'
           ,@y INT = 123;
    
    SELECT ISNULL(@x, @y) AS [ISNULL];
    SELECT COALESCE(@x, @y) AS [COALESCE];
    _

    enter image description here

    enter image description here

    ISNULLは最初の引数のデータ型を返していますが、COALESCEでは、INTの優先順位が最も高く、最初の引数値のINTへの変換が失敗するため、エラーが発生しています。

  4. 結果のNULL可能性も重要です。例えば:

    _DECLARE @x VARCHAR(3) = NULL
           ,@y VARCHAR(3) = NULL;
    
    DROP TABLE IF EXISTS [dbo].[DataSource01];
    
    SELECT ISNULL(10, 20) AS [C1]
          ,ISNULL(@x, 'text') AS [C2]
          ,ISNULL(@x, @y) AS [C3]
    INTO [dbo].[DataSource01];
    
    DROP TABLE IF EXISTS [dbo].[DataSource02];
    
    SELECT COALESCE(10, 20) AS [C1]
          ,COALESCE(@x, 'text') AS [C2]
          ,COALESCE(@x, @y) AS [C3]
    INTO [dbo].[DataSource02];
    _

    各列のNullableプロパティを確認しましょう。

    enter image description here

    enter image description here

    COALESCEを使用すると、すべての入力がNULL可能でない場合にのみ、列の_NOT NULL_プロパティがYesに設定されます。

  5. SQL標準に従って、COALESCE式は次のように変換されます。

    _CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
    _

    WHEN句のサブクエリの実行結果がNULLでない場合、SQL ServerはTHEN句で2回実行します。つまり、このような場合、2回実行されます。 WHEN句の実行結果がNULLの場合のみ、SQL Serverはサブクエリを再度実行せず、ELSE式を返します。したがって、サブクエリを使用する場合、ISNULL関数にはパフォーマンス上の利点があります。

1
gotqn