Sql

IS DISTINCTFROMとISDISTINCT FROMを書き換える方法は?



How Rewrite Is Distinct From



解決:

NSIS DISTINCT FROM述語は、SQL:1999の機能T151として導入され、その読み取り可能な否定は、IS NOT DISTINCT FROM、SQL:2003の機能T152として追加されました。これらの述語の目的は、2つの値を比較した結果が次のいずれかであることを保証することです。 NS また NS 、 一度もない わからない

これらの述語は、同等のタイプ(行、配列、多重集合を含む)で機能するため、正確にエミュレートするのはかなり複雑です。ただし、SQL Serverはこれらのタイプのほとんどをサポートしていないため、null引数/オペランドをチェックすることでかなり遠くまで到達できます。



  • a IS DISTINCT FROMbは次のように書き直すことができます。

    ((a b OR a IS NULL OR b IS NULL)AND NOT(a IS NULL AND b IS NULL))
  • a IS NOT DISTINCT FROM bは、次のように書き直すことができます。



    (NOT(a b OR a IS NULL OR b IS NULL)OR(a IS NULL AND b IS NULL))

あなた自身の答えはそれを考慮に入れていないので間違っていますFALSEまたはNULLは次のように評価されます わからない 。例えば、NULL IS DISTINCT FROM NULLは、次のように評価する必要があります NS 。同様に、1はNULLから区別されません。 NS 。どちらの場合も、式は わからない


私が好きな別のソリューションは、INTERSECTと組み合わせたEXISTSの真の2値ブール結果を活用します。このソリューションは、SQL Server2005以降で機能するはずです。

  • a IS NOT DISTINCT FROM bは、次のように書くことができます。



    EXISTS(SELECT a INTERSECT SELECT b)

文書化されているように、INTERSECTは2つのNULL値を等しいものとして扱うため、両方がNULLの場合、INTERSECTは単一の行になり、EXISTSはtrueを返します。

  • a IS DISTINCT FROMbは次のように書くことができます。

    NOT EXISTS(SELECT a INTERSECT SELECT b)

2つのテーブルで比較する必要がある複数のNULL可能列がある場合、このアプローチははるかに簡潔です。たとえば、Col1、Col2、またはCol3の値がTableAとは異なるTableBの行を返すには、次を使用できます。

SELECT * FROM TableA A INNER JOIN TableB B ON A.PK = B.PK WHERE NOT EXISTS(SELECT A.Col1、A.Col2、A.Col3 INTERSECT SELECT B.Col1、B.Col2、B.Col3);

Paul Whiteは、この回避策について詳しく説明しています:https://sql.kiwi/2011/06/undocumented-query-plans-equality-comparisons.html


SQL実装がSQL標準を実装していない場合とは異なりますIS NOT DISTINCT FROM演算子、次の同等性を使用して、それらを含む式を書き換えることができます。

一般に:

a IS DISTINCT FROM b(((a)IS NULL AND(b)IS NOT NULL)OR((a)IS NOT NULL AND(b)IS NULL)OR((a)(b)))a IS NOT DISTINCT FROM b(((a)IS NULL AND(b)IS NULL)OR((a)=(b)))

UNKNOWNとFALSEの違いが重要な状況で使用した場合、この回答は正しくありません。しかし、それは珍しいことだと思います。 @ChrisBandyによって受け入れられた回答を参照してください。

データに実際には発生しないプレースホルダー値を特定できる場合は、COALESCEは代替手段です:

a IS DISTINCT FROM b COALESCE(a、placeholder)COALESCE(b、placeholder)a IS NOT DISTINCT FROM b COALESCE(a、placeholder)= COALESCE(b、placeholder)