SQL:如何在SELECT和WHERE语句中使用布尔逻辑

时间:2015-08-07 10:35:17

标签: sql-server tsql boolean-logic

我是SQL的新手。

我已经为这个问题简化了一个复杂的SQL SELECT语句。我继承代码并且需要避免过多地改变代码。

我需要添加一些功能,只有在布尔值(@myboolean)为真时才选择额外的列:

ALTER PROCEDURE [dbo].[myProcedure]

--Parameters for the stored procedure
@myboolean as bit

AS
BEGIN
SET NOCOUNT ON;

SELECT  
    field1 AS first_field,
    field2 AS second_field,

    /* PROBLEM 1: select field3 and field4 only if @myboolean is true */
    CASE 
        WHEN (@myboolean = 1) 
          THEN 
            field3 AS third_field,  
            field4 As fourth_field,
          ELSE
            /* do nothing, select nothing here */
    END,

    field5 AS fifth_field,
    field6 AS sixth_field


    WHERE  ( ( field1.value = thisvalue

    /* PROBLEM 2: add WHERE clause to check field2.status only if @myboolean is true
     * Currently only works if @myboolean = 1. I know this should be really simple but 
     * I can't figure it out.
     * Do I need to implement a CASE statement for when @myboolean = 0? See below */
    AND ((@myboolean = 1)  AND (field2.status = 2))

    AND field1.type IN ( 1, 2 ) )  
    AND (( field1.type NOT IN ( 28, 32 )  
    OR ( field1.type IS NULL ) )) )

END

所以:

  • @myboolean为false时,应选择字段1,2,5和6 - 与原始代码一样

  • @myboolean为真时,应选择字段1-6并检查field2.status

我一直在寻找,我所能找到的只是WHERE CASE @this THEN 1 ELSE 0的例子。如果布尔值为假,我无法找到如何不检查列值。

对于问题2,我还尝试实施CASE声明,例如

    AND  field2.status  = 
         CASE
           WHEN (@myboolean = 1) 
           THEN 2 ELSE *
          END

当然这会产生一个syntax error near '*',但我无法弄清楚应该如何做。

更新 只是提醒一下,问题非常简单。原始的SELECT语句庞大而复杂。实际上有几个布尔值在起作用。我想避免在if中包装SELECT语句,因为它会很快成为混乱代码的混乱巨像。

更新 Problem 2 solved由@jpw提供(请参阅编辑回答)

3 个答案:

答案 0 :(得分:1)

我只是偶然发现了这一点,同时寻找其他东西,如果这已经解决了,那么道歉。

以下是查看问题解决方案的另一种方法:

ALTER PROCEDURE [dbo].[myProcedure]

--Parameters for the stored procedure
@myboolean as bit

AS
BEGIN
SET NOCOUNT ON;

    SELECT  

    field1 AS first_field,
    field2 AS second_field,
    field3 AS third_field,  
    field4 As fourth_field,
    field5 AS fifth_field,
    field6 AS sixth_field
    WHERE ( ( field1.value = thisvalue
    AND ((@myboolean = 1)  AND (field2.status = 2))
    AND field1.type IN ( 1, 2 ) )  
    AND (( field1.type NOT IN ( 28, 32 )  
    OR ( field1.type IS NULL ) )) )

    UNION

    SELECT  

        field1 AS first_field,
        field2 AS second_field,
        NULL AS third_field,  
        NULL As fourth_field,
        field5 AS fifth_field,
        field6 AS sixth_field
        WHERE  ( ( field1.value = thisvalue
        AND ((@myboolean != 1)  AND (field2.status = 2))
        AND field1.type IN ( 1, 2 ) )  
        AND (( field1.type NOT IN ( 28, 32 )  
        OR ( field1.type IS NULL ) )) )

END

免责声明:我没有测试过这段代码,它是一个复制和粘贴工作,稍微调整一下,但我希望它能以一种新的方式给你一个新的方向,使用UNION并根据设置返回结果集参数。

答案 1 :(得分:0)

第一个问题的答案是,您无法动态选择要在查询中输出的列,但您必须更改逻辑"外部"使用流语句控件(if-else)或动态sql(使用根据所使用的变量选择的部分连接最终查询字符串)的查询。

如你所知,有很多变数很快就会失控,所以"最好的"解决方案可能是将大型语句分解为几个较小的部分,然后根据需要将它们粘合在一起。视图也可能是将代码重构为不太复杂的东西的工具。

要回答问题的第二部分,应该起作用的条件是:

AND ((@myboolean = 1 AND field2.status = 2) OR @myboolean = 0)

答案 2 :(得分:0)

我在这里有点深入,因为我之前没有使用CASE,但我在W3Schools sql editor尝试了以下内容,它似乎可以解决问题:

SELECT CustomerId,
  CASE WHEN customerId < 5 -- Problem 1, first field
    THEN CustomerName
  END as optCustomerName,
  CASE WHEN customerId > 3 -- Problem 1, second field
    THEN ContactName
  END optContactName
FROM Customers
WHERE
  CustomerId < 15
  AND 
    CASE WHEN CustomerId < 5 -- Problem 2, a complete condition
       THEN CustomerName like 'an%'
       ELSE 1
    END;

以下是有关我的代码的一些注释,以及您需要对代码进行的相应更改:

  • 在我的示例中,我使用了customerId < 5代替@myboolean = 0
  • 似乎CASE语句要替换SELECT子句中的一个且只有一个列定义,因此您需要两个CASE来包含field3 }和field4
  • 我强烈建议对CASE列定义进行别名,因为它看起来很丑陋: - )
  • 由于SELECT中的字段数应该是常量,因此默认行为是在不满足条件时添加null值。如果不需要,我相信你需要使用另一个答案中建议的IF语句的一些变体
  • 当使用CASE而不是where条件时,它看起来更好,并且如果你包围整个部分,然后在它不匹配时提供正确的默认值,则更容易阅读

有了这些知识,我建议您对代码进行以下更改:

...
field2 AS second_field,

CASE WHEN (@myboolean = 1) THEN field3
END as third_Field,

CASE WHEN (@myboolean = 1) THEN field4
END as fourth_Field,

field5 AS fifth_field,
...

WHERE  
  ...
  AND
    CASE 
       WHEN (@myboolean = 1) THEN field2.status = 2  
       ELSE 1 -- Always true, when not hitting the when @myboolean 
    END
  AND
  ...

在这里和那里留下片段,特别是在WHERE子句中,因为它看起来有点混乱所有的括号。但是你应该得到如何做出改变的概念。

相关问题