sql >> データベース >  >> RDS >> Sqlserver

SQLServerのCOALESCE関数に関する5つの質問に対する上位の回答

    SQLのCOALESCE関数はどれほどクールですか?

    私にとってとても重要なのは十分にクールです。そして、COALESCEの目標を無視するという悪い習慣を持たない新しい男を雇うことはとても幸せです。これには、同様の状況を処理するための他の式や関数が含まれます。

    今日、SQLCOALESCE式に関して最もよく聞かれる5つの質問に対する回答が見つかります。これらの1つは、何度も何度も議論されています。

    始めましょうか?

    SQLでのCOALESCE関数の使用とは何ですか?

    それは2つの言葉で答えることができます:ヌルの処理

    ヌルは値の無効です。言い換えれば、不明です。空の文字列やゼロの数字とは異なります。 nullを処理するには、式と関数を使用する必要があります。そのうちの1つはCOALESCEです。

    私の意味を理解するには、以下のステートメントを参照してください。

    DECLARE @number INT
    
    SELECT @number + 33587

    正常に動作しますか?

    問題はありますか?現時点ではありません。

    ただし、数値にnullを追加するとNULLに等しいため、ステートメントの結果はNULLになります。

    すべてのクエリがこのレベルにしか下がらない場合は、読むのをやめることができます。しかしもちろん、そうではありません。この種のコードを作成するだけでなく、多くの報酬を受け取っています。

    それでは、「災害」を少し追加しましょう。

    DECLARE @number INT
    
    SET @number = @number + 33587
    
    UPDATE myTable
    set col1 = @number   -- Surprise! col1 is NOT NULLABLE
    where ID = 1
    
    PRINT 'Success!'

    上記のコードの実行は、UPDATEステートメントに到達したときに行き止まりになります。 null不可能な列にnullを設定できないため、「Success!」は出力されません。このステートメントは、nullを処理する必要がある理由を明確に示していますか?

    コードを変更してセーフティネットを追加しましょう:

    DECLARE @number INT
    
    SET @number = COALESCE(@number,0) + 33587     -- our safety net. Thanks to COALESCE.
    
    UPDATE myTable
    set col1 = @number               -- Disaster averted!
    where ID = 1
    
    PRINT 'Success!'

    COALESCEはnull値をゼロに変更し、合計はnullになりません。

    教訓は、COALESCEはヌルに対するセーフティネットの1つであるということです。さらに良いことに、SQLコードでnullを適切に処理すると、頭痛の種が減り、早く家に帰ることができます。それは確かです。

    これで、私のチームにnullの処理に熱心な人が必要な理由がわかりました。

    SQLCOALESCEの使用におけるより実用的な例

    より実用的な例を参照してみましょう。

    ミドルネームを持っている人もいれば、持っていない人もいる地域に住んでいるとします。ヌルトラップに陥ることなく、ファーストネーム、ミドルネーム、ラストネームからフルネームをどのように形成しますか?

    COALESCEを使用した1つの可能な解決策は次のとおりです。

    USE AdventureWorks
    GO
    
    SELECT
    p.LastName + ', ' + p.FirstName + ' ' + COALESCE(p.MiddleName + ' ','') AS FullName
    FROM Person.Person p

    別の例:あなたが会社の従業員であり、総賃金が従業員ごとに異なる方法で計算されているとします。それらのいくつかのために、時給があります。他の人は毎週または毎月の料金で支払われます。

    COALESCEを使用したクエリソリューションと一緒に表のサンプルを次に示します。

    -- STEP 1: Create the table
    CREATE TABLE EmployeeWages (
        employee_id INT PRIMARY KEY,
        hourly_rate SMALLMONEY,
        weekly_rate SMALLMONEY,
        monthly_rate MONEY,
        CHECK(
            hourly_rate IS NOT NULL OR
            weekly_rate IS NOT NULL OR
            monthly_rate IS NOT NULL)
    );
    
    -- STEP 2: Insert data
    INSERT INTO
        EmployeeWages(
            employee_id,
            hourly_rate,
            weekly_rate,
            monthly_rate
        )
    VALUES
        (1,60, NULL,NULL),
        (2,40, NULL,NULL),
        (3,NULL, 1000,NULL),
        (4,NULL, NULL,7000),
        (5,NULL, NULL,5000);
    
    -- STEP 3: Query the monthly salary.
    SELECT
        employee_id,
        COALESCE(
            hourly_rate*22.00*8.00,
            weekly_rate*4.00,
            monthly_rate
        ) AS monthly_salary
    FROM
        EmployeeWages;

    この表には、従業員IDごとに異なる支払いモードが含まれています。このクエリでは、すべての人の月給を出力する必要があります。

    これがCOALESCEの魅力です。値のリストを受け入れ、アイテムはいくつでも存在できます。 COALESCEは、nullではない最初のものを選択します:

    きちんとしていますね

    COALESCEはSQLでどのように機能しますか?

    COALESCEの定義は、値のリストから最初のnull以外の値を返す式です。 COALESCE構文は次のとおりです。

    COALESCE(式[、…n])

    賃金の支払いモードが異なる前の例は、これを示しています。

    フードの下にあるもの

    内部的には、SQLのCOALESCE関数は、はるかに長いCASE式の糖衣式です。これにより、同等のCASEを入力する必要がなくなります。これは、より長い(そして、私のような怠惰なタイピストにとっては疲れます)。結果は同じになります。

    それを証明できますか?はい! 1つは、Microsoftがそれを認めていることです。

    しかし、私たちにとっては良いことですが、Microsoftはそれを実行計画に含めました。したがって、何が起こっているのかがわかります。

    前の例の賃金を使って試してみましょう。ただし、以下のクエリを再実行する前に、実際の実行プランを含めるをオンにしてください。 または、 CTRL-Mを押すだけです 。

    SELECT
        employee_id,
        COALESCE(
            hourly_rate*22.00*8.00,
            weekly_rate*4.00,
            monthly_rate
        ) AS monthly_salary
    FROM
        EmployeeWages;

    実行プランをクリックします 結果のタブ。シンプルに見えますが、私たちの隠された宝石はコンピュートスカラーにあります ノード。その上にマウスを置くと、 Expr1002という名前の式が表示されます。 (図2)。何でしょうか?

    もっと深く掘り下げましょう。それを右クリックして、実行プランXMLを表示を選択します 。新しいウィンドウが表示されます。以下の図3をご覧ください:

    CASEステートメントがあります。以下は、読みやすくするためにフォーマットおよびインデントされたもの全体です。

    CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                                *(22.00)*(8.00) IS NOT NULL
         THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                           [TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)*(22.00)*(8.00),0)
         ELSE CASE WHEN    
              CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)
                                                *(4.00) IS NOT NULL
              THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),                                                         
                           [TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),0)
              ELSE CONVERT_IMPLICIT(numeric(23,8),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0)
              END
    END

    と比べるとかなり長いです
    COALESCE(
            hourly_rate * 22.00 * 8.00,
            weekly_rate * 4.00,
            monthly_rate
            )

    これが、SQLServerがCOALESCEを使用したクエリで行ったことです。すべては、値のリストでnullではない最初の値を取得するためのものです。

    短くすることはできますか?

    私はあなたが何を考えているか知っています。 SQL Serverがクエリ処理中にこれを行う場合、COALESCEは低速である必要があります。 CONVERT_IMPLICITの複数の出現は言うまでもありません。代わりに使用しますか?

    1つは、短いCASEステートメントを自分で入力できます。または、ISNULLを使用できます。これについては後で詳しく説明します。遅いと言えば、この投稿が終わる前にそれをカバーしてもらいました。

    SQLのCOALESCEとISNULLの違いは何ですか?

    COALESCEの代替手段の1つはISNULLです。 2つの値でCOALESCEを使用すると、ISNULLに似たものになります。少なくとも、結果は似ています。それでも、顕著な違いがあります。 COALESCEとISNULLのどちらを使用するかを決定するためのガイドとして使用できます。

    (1)ISNULLは2つの引数を受け入れます。 COALESCEは引数のリストを受け入れます

    それが最も明らかな違いです。構文からすると、それは確かに異なります。

    ISNULL(check_expression、replacement_value)
    COALESCE(式[、…n])

    2つの引数で両方を使用すると、結果は同じになります。以下の2つのステートメントは1になります:

    SELECT ISNULL(NULL, 1)
    SELECT COALESCE(NULL, 1)

    結果は同じですが、意味が異なります。

    • 最初の引数がNULLであるため、ISNULL(NULL、1)は1を返しました。
    • COALESCE(NULL、1)は1を返しました。これは、1がリストの最初の非null値であるためです。 。

    (2)COALESCEはSQL-92標準です

    それは正しい。確認できます。たとえば、SQLコードをSQL ServerからMySQLに移植する場合、COALESCEは同じように機能します。図4を参照し、図1の結果を比較してください:

    ただし、MySQLでISNULLを使用すると、SQLServerの構文を使用するとエラーが発生します。

    例:SQL ServerManagementStudioおよびMySQLWorkbenchで次を実行します。

    SELECT ISNULL(null,1)

    どうしたの? SQL Serverでは、出力は1です。しかし、MySQLでは、出力はエラーです:

    06:36:52 SELECT ISNULL(null、1)エラーコード:1582。ネイティブ関数「ISNULL」の呼び出しでのパラメータ数が正しくありません

    つまり、MySQLのISNULLは1つの引数を受け入れ、引数がnullの場合は1を返します。それ以外の場合は、0を返します。

    (3)COALESCEで2つのヌルを渡すと、エラーがトリガーされます。 ISNULLで問題ありません

    これによりエラーが発生します:

    SELECT COALESCE(NULL, NULL)

    エラーは次のとおりです。「COALESCEの引数の少なくとも1つは、NULL定数ではない式である必要があります。」

    これで問題ありません:

    SELECT ISNULL(NULL, NULL)

    COALESCEコードを以下のようなものに変更しても、エラーは発生しません:

    DECLARE @value INT = NULL
    SELECT COALESCE(@value,null)

    これは、 @value ヌル定数ではありません。

    (4)SQLCOALESCEはCASEに変換されます。 ISNULLはISNULLのままです

    これは、 「SQLでCOALESCEはどのように機能しますか?」で確認できます。 セクション。ここで、別の例を見てみましょう:

    SELECT
    P.LastName + ', ' + P.FirstName + ' ' + COALESCE(P.MiddleName + ' ','') AS FullName
    FROM Person.Person p

    実行計画XMLの検査 スカラー演算子の場合、CASEへの変換が明らかになります:

     [AdventureWorks].[Person].[Person].[LastName] as [p].[LastName]+N', '
    +[AdventureWorks].[Person].[Person].[FirstName] as [p].[FirstName]+N' '
    +CASE WHEN ([AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' ') IS NOT NULL
          THEN [AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' '
          ELSE N''
     END

    次に、ISNULLを使用して同等のクエリを実行します:

    SELECT
    P.LastName + ', ' + P.FirstName + ' ' + ISNULL(P.MiddleName + ' ','') AS FullName
    FROM Person.Person p

    次に、実行計画XMLを調べます スカラー演算子の場合:

     [AdventureWorks].[Person].[Person].[LastName] as [p].[LastName]+N', '
    +[AdventureWorks].[Person].[Person].[FirstName] as [p].[FirstName]+N' '
    +isnull([AdventureWorks].[Person].[Person].[MiddleName] as [p].[MiddleName]+N' ',N'')

    ISNULLはまだISNULLです。

    (5)結果の式のデータ型が異なります

    結果の式のデータ型の決定も、COALESCEとISNULLで異なります:

    • ISNULLは、最初のパラメーターのデータ型を使用します。
    • COALESCEは、優先順位が最も高い値のデータ型を返します。

    データ型の優先順位のリストについては、このリンクを確認してください。

    例を見てみましょう:

    SELECT
     employee_id
    ,COALESCE(CAST(weekly_rate * 4 AS MONEY),0.0000) AS monthly_rate
    FROM EmployeeWages

    次に、実行プランXMLでCASEへの変換を調べます。 :

    CASE WHEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]
                                               *CONVERT_IMPLICIT(smallmoney,[@1],0),0) IS NOT NULL
         THEN CONVERT_IMPLICIT(numeric(19,4), CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]
                                               *CONVERT_IMPLICIT(smallmoney,[@1],0),0),0)
         ELSE (0.0000)
    END

    上記のCASE式では、結果のデータ型は neuro(19,4)になります。

    なんで? お金よりも優先されます およびsmallmoney お金にキャストしても 。なぜ数値 お金ではありません ?定数0.0000のため。

    @ 1とは何か疑問に思われる場合は、実行プランXML 答えがあります。定数4です。

    <ParameterList>
     <ColumnReference Column="@1" ParameterDataType="int" ParameterCompiledValue="(4)"  
           ParameterRuntimeValue="(4)" />
    </ParameterList>

    ISNULLで試してみましょう:

    SELECT
     employee_id
    ,ISNULL(CAST(weekly_rate * 4 AS MONEY),0.0000) AS monthly_rate
    FROM EmployeeWages

    繰り返しますが、スカラー演算子を探してください のScalarString

    ISNULL(CONVERT(MONEY,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate]*($4.0000),0),($0.0000))

    最後に、結果の式のデータ型はお金になります 。これは最初の引数のデータ型です。

    データの優先順位を上回る方法

    コードにいくつかの変更を加えることで、データの優先順位を「アウトスマート」にすることができます。以前の結果には、数値が含まれていました データ・タイプ。結果をお金にしたい場合 データ型を指定してCONVERT_IMPLICITを削除するには、次の手順を実行します。

    SELECT
     employee_id
    ,COALESCE(CAST(weekly_rate AS MONEY) * ($4.0000),($0.0000)) AS monthly_rate
    FROM EmployeeWages

    ($ 4.000)と($ 0.0000)の定数に気づきましたか?それらはお金です 定数。次に何が起こるかは、実行計画XMLに表示されます のScalarString

    CASE WHEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*($4.0000) IS NOT NULL 
         THEN CONVERT(money,[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*($4.0000) 
         ELSE ($0.0000) 
    END

    それははるかに良いです。短くなり、CONVERT_IMPLICITはなくなりました。結果のデータ型はお金です 。

    (6)結果の式のNULL可能性が異なります

    ISNULL(NULL、1)とCOALESCE(NULL、1)の結果は似ていますが、null可能性の値は異なります。 COALESCEはnull許容です。 ISNULLはそうではありません。これは、計算列で使用するとわかります。

    例を見てみましょう。 PRIMARY KEYはNULL値を受け入れることができないため、以下のステートメントはエラーをトリガーします。同時に、 column2のCOALESCE式のnull可能性 NULLと評価されます。

    CREATE TABLE NullabilityDemo  
    (  
      column1 INTEGER NULL,  
      column2 AS COALESCE(column1, 0) PRIMARY KEY,  
      column3 AS ISNULL(column1, 0)  
    );

    ISNULL関数のnull可能性はASNOTNULLと評価されるため、このステートメントは成功します。

    CREATE TABLE NullabilityDemo  
    (  
      column1 INTEGER NULL,  
      column2 AS COALESCE(column1, 0),  
      column3 AS ISNULL(column1, 0) PRIMARY KEY  
    );

    (7)ISNULLの左引数は1回評価されます。 COALESCEの反対です

    前の例をもう一度考えてみましょう:

    SELECT
        employee_id,
        COALESCE(
            hourly_rate*22.00*8.00,
            weekly_rate*4.00,
            monthly_rate
        ) AS monthly_salary
    FROM
        EmployeeWages;

    次に、 ScalarStringを調べます このために:

    CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                                  *(22.00)*(8.00) IS NOT NULL 
         THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                                                  [TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)
                                                  *(22.00)*(8.00),0) 
         ELSE CASE WHEN CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)
                                                  *(4.00) IS NOT NULL 
                   THEN CONVERT_IMPLICIT(numeric(23,8),CONVERT_IMPLICIT(numeric(10,4),
                                            [TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),0) 
                   ELSE CONVERT_IMPLICIT(numeric(23,8),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0) 
              END 
    END

    SQLのCOALESCE関数がCASEに変換されると、各式は2回評価されます(最後の式を除く)。上記のように、 hourly_rate * 22.00 * 8.00 二度登場。 weekly_rate * 4.00でも同じです 。最後の式、 monthly_rate 、一度登場しました。

    COALESCEは式を2回評価するため、パフォーマンスが低下する可能性があります。これについては後で詳しく説明します。

    ただし、同等のISNULLを確認してください:

    SELECT
     employee_id,
     ISNULL(hourly_rate * 22.00 * 8.00,ISNULL(weekly_rate * 4.00,monthly_rate)) AS  
                                                           monthly_salary
    FROM EmployeeWages

    次に、 ScalarStringを検査します 実行計画XML

    isnull(CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[hourly_rate],0)*(22.00)*(8.00),
           CONVERT_IMPLICIT(numeric(19,8),
    isnull(CONVERT_IMPLICIT(numeric(10,4),[TestDatabase].[dbo].[EmployeeWages].[weekly_rate],0)*(4.00),
    CONVERT_IMPLICIT(numeric(14,6),[TestDatabase].[dbo].[EmployeeWages].[monthly_rate],0)),0))

    上記のように、 hourly_rate weekly_rate 、および monthly_rate 一度だけ登場しました。したがって、ISNULLで式が2回評価されることを心配する必要はありません。

    WHERE句でCOALESCEを使用できますか?

    確実なこと。これを証明する例を示すよりも良い方法はありません。

    -- Query all the names in Person table with no middle name
    
    USE AdventureWorks
    GO
    
    SELECT
     p.LastName
    ,p.FirstName
    FROM person.Person p
    WHERE COALESCE(p.MiddleName,'') = ''

    MiddleName の場合、COALESCEは空白の文字列を返します 無効である。もちろん、結果を出すためのより短い方法があります。しかし、これはCOALESCEがWHERE句で機能することを示しています。

    どちらが速いですか:COALESCEまたはISNULL?

    最後に、注目のトピックであるパフォーマンスに到達しました。

    テストと比較を含む多くのページが表示されますが、コメントではCOALESCEとISNULLの支持者の戦いがあります。それらの戦争のほこりや煙を一掃します。

    COALESCEとISNULLのどちらが速いですか?答えは次のとおりです。

    (ドラムローリング)

    依存します!

    (あごを落とした)

    残念だった?すぐに説明します。

    まず、経過時間をメトリックとして使用すると、両方にパフォーマンスの違いがあるように見えることに同意します。 SQL ServerがCOALESCEをCASEステートメントに変換するときに、この事実を支持する人もいました。その間、ISNULLはそのままです。

    結果が異なるため、他の人は異なる理由で推論する可能性があります。また、彼らにとって、COALESCEからCASEへの変換は、まばたきよりも高速です。このスレッドで指摘されているように、パフォーマンスの違いは「ごくわずか」です。私は同意します。これは、違いが「わずか」であると述べた別の記事です。

    ただし、ここで重要なことがあります。ごくわずかな経過時間をメトリックとして信頼できるでしょうか。本当に重要なのは、クエリの論理読み取り量です。これは、次の例で指摘する内容です。

    (論理読み取りに関する他の記事と、この要因がクエリに遅れをとる理由を確認してください。)

    例1

    同じ例を調べて、それらの論理読み取りと実行計画を比較してみましょう。これを実行する前に、STATISTICS IOがオンになっていて、実際の実行プランを含めることを確認してください。 有効になっています。

    SET STATISTICS IO ON
    
    SELECT
    P.LastName + ', ' + P.FirstName + ' ' + COALESCE(P.MiddleName + ' ','') AS FullName
    FROM Person.Person p
    
    SELECT
    P.LastName + ', ' + P.FirstName + ' ' + ISNULL(P.MiddleName + ' ','') AS FullName
    FROM Person.Person p

    事実は次のとおりです。

    両方のクエリの論理読み取りは同じです。どちらも107*8KBのページです。もちろん、100万件のレコードがある場合、論理読み取りは増加します。ただし、両方のクエリの論理読み取りは等しくなります。 COALESCEがCASEに変換された場合でもそうです:

    実行計画を調べてみましょう。これが私たちがそれを行う方法です:

    1. COALESCE式を使用して最初のSELECTステートメントを実行します。
    2. 実行プランをクリックします 結果のタブ。それを右クリックして、名前を付けて実行プランを保存を選択します 。そして、ファイルに plan1.sqlplanという名前を付けます。 。
    3. ISNULL関数を使用して2番目のSELECTステートメントを実行します。
    4. 実行プランをクリックします 結果のタブ。
    5. 右クリックして、[ショープランの比較]を選択します 。
    6. ファイルplan1.sqlplanを選択します 。新しいウィンドウが表示されます。

    これが、すべての例の実行計画を検査する方法です。

    最初の例に戻り、実行プランの比較を確認するには、図6を参照してください。

    図6のこれらの重要なポイントに気づきましたか?

    • 2つのプラン(インデックススキャン)の影付きの部分は、SQLServerが2つのクエリに同じ操作を使用したことを意味します。
    • QueryPlanHash 2つのプランの場合は0x27CEB4CCE12DA5E7です。これは、プランが両方で同じであることを意味します。
    • 経過時間の数ミリ秒の違いはごくわずかです。

    要点

    リンゴとリンゴを比較するようなものですが、種類は異なります。 1つは日本のふじりんご、もう1つはニューヨークの赤いりんごです。それでも、どちらもリンゴです。

    同様に、SQL Serverには、両方のクエリに対して同じリソースと選択された実行プランが必要です。唯一の違いは、COALESCEまたはISNULLの使用です。最終結果は同じであるため、わずかな違いがあります。

    例2

    COALESCEとISNULLの両方の引数としてサブクエリを使用すると、大きな違いが現れます。

    USE AdventureWorks
    GO
    
    SELECT COALESCE(
           (SELECT
            SUM(th.ActualCost)
            FROM Production.TransactionHistory th
            WHERE th.ProductID = 967)
           ,0) 
    
    SELECT ISNULL(
           (SELECT
            SUM(th.ActualCost)
            FROM Production.TransactionHistory th
            WHERE th.ProductID = 967)
           ,0)

    上記のコードでも同じ結果になりますが、内部は大きく異なります。

    論理的な読み取りから始めましょう:

    COALESCE式を含むSELECTステートメントには、ISNULLを使用したステートメントの2倍の論理読み取りがあります。

    しかし、なぜ論理読み取りを2倍にするのでしょうか。実行計画の比較により、さらに多くのことが明らかになります:

    図8は、COALESCEを使用して論理読み取りが2倍になる理由を説明しています。一番下の計画の2つのStreamAggregateノードを参照してください。これらは重複しています。次の質問は、なぜそれが複製されたのかということです。

    COALESCEがCASEに変換されるタイミングに関連するポイントを思い出してみましょう。引数で式が評価されるのは何回ですか? TWICE!

    したがって、サブクエリは2回評価されます。重複ノードがある実行プランに表示されます。

    これは、ISNULLと比較したCOALESCEを使用した二重論理読み取りについても説明しています。 COALESCEを使用してクエリの実行プランXMLを確認する場合は、かなり長くなります。ただし、サブクエリが2回実行されることがわかります。

    それで?これを裏切ることはできますか?もちろん!まれだと思うこのような問題に直面したことがある場合、可能な解決策は分割統治法です。または、サブクエリが1つしかない場合は、ISNULLを使用します。

    サブクエリ式の2回の評価を回避する方法

    サブクエリを2回評価しないようにする方法は次のとおりです。

    • 変数を宣言し、サブクエリの結果を変数に割り当てます。
    • 次に、変数を引数としてCOALESCEに渡します。
    • サブクエリの数に応じて、同じ手順を繰り返します。

    私が言ったように、それはまれなはずですが、それが起こった場合、あなたは今何をすべきかを知っています。

    隔離レベルに関するいくつかの言葉

    サブクエリを2回評価すると、別の問題が発生する可能性があります。クエリの分離レベルによっては、マルチユーザー環境での最初の評価の結果が2番目の評価と異なる場合があります。クレイジーです。

    安定した結果が返されるようにするには、SNAPSHOTISOLATIONを使用してみてください。また、ISNULLを使用することもできます。または、上記のように分割統治法にすることもできます。

    要点

    それで、本質は何ですか?

    • 常に論理読み取りを確認してください。それは経過時間よりも重要です。経過時間を使用して、正気を取り除いてください。マシンと本番サーバーの結果は常に異なります。休憩してください。
    • 実行計画を常に確認して、内部で何が起こっているかを把握してください。
    • COALESCEがCASEに変換されると、式が2回評価されることに注意してください。次に、サブクエリなどが問題になる可能性があります。 COALESCEで使用する前に、サブクエリの結果を変数に割り当てることが解決策になる可能性があります。
    • 何が高速かは、論理読み取りの結果と実行計画によって異なります。 COALESCEとISNULLのどちらが速いかを判断する一般的なルールはありません。そうしないと、HierarchyIDやSQL Graphの場合と同様に、Microsoftがそのことを通知する可能性があります。

    最終的に、それは本当に異なります。

    結論

    この記事を読む価値があったことを願っています。話し合ったポイントは次のとおりです。

    • COALESCEは、nullを処理する方法の1つです。コードのエラーを回避するためのセーフティネットです。
    • 引数リストを受け入れ、最初のnull以外の値を返します。
    • クエリ処理中にCASE式に変換されますが、クエリの速度は低下しません。
    • ISNULLにはいくつかの類似点がありますが、7つの顕著な違いがあります。
    • WHERE句で使用できます。
    • 最後に、ISNULLより速くも遅くもありません。

    この投稿が気に入ったら、ソーシャルメディアボタンがクリックを待っています。共有は思いやりがあります。

    ありがとうございます。

    また読む

    初心者向けのSQLCOALESCE関数を使用したNULL値の効果的な処理

    SQLCOALESCE関数の実用的な使用


    1. 大学院レベルのエラー処理

    2. インスタンス上のすべてのデータベースで同じクエリを実行するにはどうすればよいですか?

    3. Oracleで日付をフォーマットする方法

    4. B+treeとHashを比較したデータベースのインデックス作成