3

TRUE/FALSE状態を格納するためのビットフィールドを含むSQLExpressテーブルがあります。

何かのようなもの:

+----+---------+
| ID | IsAlive |
+----+---------+
| 1  |    1    |
| 2  |    0    |
| 3  |   NULL  |
| 4  |    1    |
+----+---------+

そのテーブルを例として使用して、次のいずれかを実行する1つのストアドプロシージャを作成します。

  1. すべてのレコードを取得します。
  2. を含むレコードのみを取得しIsAlive=1ます。
  3. を含むレコードのみを取得しIsAlive=0 or NULLます。

IF / ELSE条件を記述せずにクエリを作成する方法を考えようとしています-次のようなことを行うよりも、より良い/よりクリーンな方法があるようです。

-- The ternary logic...
-- 0 or NULL retrieves records where IsAlive = 0 or NULL
-- 1 retrieves records where IsAlive = 1
-- Otherwise return all records 

-- sproc .....

    @IsAlive tinyint = 2 -- Return all records by default

    AS
    BEGIN
      IF(@SentToNTService = 0 OR @SentToNTService = 1)
       BEGIN
        SELECT *
        FROM MyTable
        WHERE IsAlive = @IsAlive;
       END
    ELSE -- Lame redundancy 
       BEGIN
        SELECT *
        FROM MyTable
       END  
    END

上記のように2つの異なるクエリを作成せずに、同じ結果を作成する別の方法はありますか?

4

5 に答える 5

5

これを行う方法の2つの提案:

変数@isaliveも「ビット」として宣言されていると仮定します(これはそうあるべきです)

SELECT * FROM @t
WHERE @isalive is null or @isalive = coalesce(isalive, 0)

@isaliveが「ビット」である必要のない「ビット比較」ソリューションを使用する場合(ビットとtinyintで機能します)

SELECT * FROM @t
WHERE coalesce((1-coalesce(isalive, 0)) ^ @isalive, 1) > 0

2番目の解決策は私のようなオタクのためのものです。一部の筋金入りの人々は、それが可能な限り最高のパフォーマンスを提供すると思うので、それが面白い(または少なくとも面白い)と感じるかもしれません(私が間違っている場合は誰かが私を訂正してください)。これは強力なソリューションですが、読みにくいです。

于 2011-07-24T05:54:02.283 に答える
3

これはあなたが望むことをします:

    SELECT *
    FROM MyTable
    WHERE COALESCE(IsAlive, 0) = COALESCE(@IsAlive, COALESCE(IsAlive, 0))

@IsAliveの値に基づく:

  1. NULLの場合、すべてを返します(条件が常にtrueであるため)
  2. 1の場合、IsAlive=1の行を返します
  3. 0の場合、IsAlive=0またはNULLの行を返します

COALESCEは、NULLでない限り、最初の引数を返す関数です。NULLの場合は、2番目の引数を返します。

したがって、LHSはIsAliveがNULLの場合は0を返し、IsAliveが1の場合は1を返します。RHSはストアドプロシージャ引数@IsAliveがNULLの場合は同じものを返し、それ以外の場合は@IsAlive引数を返します。

編集: これは、@IsAliveがBITであると想定しています。tinyintの場合、caseステートメントを追加できます。

    SELECT *
    FROM MyTable
    WHERE COALESCE(IsAlive, 0) = CASE @IsAlive
                                    WHEN 0 THEN 0
                                    WHEN 1 THEN 1
                                    ELSE COALESCE(IsAlive, 0)
                                 END
于 2011-07-23T23:30:32.923 に答える
1

これを試して:

SELECT * FROM MyTable WHERE ISNULL (IsAlive, 0) = ISNULL (@IsAlive, 0)
UNION
SELECT * FROM MyTable WHERE ISNULL (@IsAlive, 0) > 1
于 2011-07-23T23:33:58.180 に答える
1

これは正確ではありませんが、あなたができることにかなり近いです:

SELECT *        
FROM MyTable        
WHERE CASE @IsAlive
      WHEN 0 THEN IsAlive = @IsAlive
      WHEN 1 THEN IsAlive = @IsAlive
      ELSE 1=1 --dummy true value, when null or anything else
END
于 2011-07-23T23:34:56.797 に答える
1

このようなものも機能するはずです。

SELECT *        
FROM MyTable        
WHERE (@IsAlive = 0 and IsAlive=0)
OR (@IsAlive =1 and IsAlive =1)
OR (@IsAlive is null) 
于 2011-07-24T05:56:27.540 に答える