如何在T-SQL中的位字段上创建三元条件

时间:2011-07-23 23:23:53

标签: sql tsql sql-server-2008 conditional-statements ternary

我有一个SQLExpress表,其中包含一个用于存储TRUE / FALSE状态的位字段。

类似的东西:

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

使用该表作为示例,我想创建一个将执行以下任一操作的存储过程:

  1. 检索所有记录。
  2. 仅检索IsAlive=1的记录。
  3. 仅检索IsAlive=0 or NULL的记录。
  4. 我正在考虑如何创建我的查询而不必编写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
    

    是否有另一种创建相同结果的方法,而不必像上面那样创建两个不同的查询?

5 个答案:

答案 0 :(得分:5)

有关如何执行此操作的2条建议:

假设你的变量@isalive也被声明为'bit'(应该是)

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

如果你想使用'比较'解决方案,不需要@isalive为'bit'(它可以用于bit和tinyint)

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

第二种解决方案适用于像我这样的书呆子。一些铁杆人可能会发现它很有趣(或者至少是有趣的)因为我认为它提供了最好的性能(如果我错了,请有人纠正我)。这是一个强大的解决方案,但很难阅读。

答案 1 :(得分:3)

这将做你想要的:

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

基于@IsAlive的值:

  1. 如果为NULL,则返回所有内容(因为条件始终为true)
  2. 如果为1,则返回IsAlive = 1
  3. 的行
  4. 如果为0,则返回IsAlive = 0或NULL
  5. 的行

    COALESCE是一个函数,它返回它的第一个参数,除非它是NULL,在这种情况下它返回它的第二个参数。

    因此,如果IsAlive为NULL或0,则LHS返回0;如果IsAlive为1,则LHS返回1。 当存储过程参数@IsAlive为NULL时,RHS返回相同的值,否则返回@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
    

答案 2 :(得分:1)

试试这个:

SELECT * FROM MyTable WHERE ISNULL (IsAlive, 0) = ISNULL (@IsAlive, 0)
UNION
SELECT * FROM MyTable WHERE ISNULL (@IsAlive, 0) > 1

答案 3 :(得分: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

答案 4 :(得分:1)

这样的事情也应该有效。

SELECT *        
FROM MyTable        
WHERE (@IsAlive = 0 and IsAlive=0)
OR (@IsAlive =1 and IsAlive =1)
OR (@IsAlive is null)