代码之家  ›  专栏  ›  技术社区  ›  Nick

WHERE中的SQL-CASE表达式

  •  7
  • Nick  · 技术社区  · 17 年前

    我在这里阅读了关于在WHERE子句中使用CASE表达式的内容:

    http://scottelkin.com/sql/using-a-case-statement-in-a-sql-where-clause/

    我试图使用它来根据用户应用程序传递的合同号过滤select语句中的结果。无论传入什么,我的代码当前都会抛出“无效参数”错误。我验证了SELECT/FROM工作正常,就像没有CASE表达式的where子句一样。这是我的代码。

    WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
    tblContracts.ContractNo)
    

    代码的冗余是为了进行故障排除,我计划稍后在CASE上使用通配符过滤。我现在正专注于简化语法。我认为这应该返回参数与表中存储的合同号匹配的所有记录。任何帮助或建议都将不胜感激。

    12 回复  |  直到 13 年前
        1
  •  9
  •   casperOne    15 年前

    你确定要这样做吗?您的案例陈述总是会返回 @ContractNo .我想你要找的是:

    where 
        case @ContractNo 
            when 0 then tblContracts.ContractNo 
            else @ContractNo 
        end = tblContracts.ContractNo
    

    上面的过滤器说“给我合同 ContractNo 等于参数,如果参数为0,则等于所有参数。

    前面的过滤器仅在合同编号字段与参数完全相等的情况下进行过滤。

    无论如何,你应该这样做:

    where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo
    

    逻辑更容易理解,除此之外(不要引用我的话),优化器可能会在case语句之外更好地工作。

        2
  •  7
  •   Community Mohan Dere    9 年前

    在阅读了你的解释后,有一个更好的方法可以做到这一点 CASE :

    WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo
    

    这将只返回匹配的合同编号,除非 @ContractNo 为0,在这种情况下,它将返回所有记录。

    编辑: 我刚刚注意到 casperOne proposed the same thing 我没看到。把自己放大。

        3
  •  2
  •   dkretz    17 年前

    试着去掉括号,反正括号放错了地方——正确的括号应该在“END”之后。

        4
  •  2
  •   Manu JCasso    17 年前

    也许你忘了申报@ContractNo?它是否与0和tblContracts相当。合同号?

        5
  •  1
  •   Nick Nick    17 年前

    Recursive的帖子准确地解决了我的问题。

    我看到有人抱怨我最初的帖子不够清晰。将来,我该怎么做才能让我说的更直截了当?我不习惯对代码提出问题,并为它的任何混乱之处道歉。我是否只需要像在第二篇帖子中那样提供详细信息?

    再次感谢大家的帮助。

        6
  •  1
  •   BenAlabaster    17 年前

    将右括号移动到=之前,如下所示:

    WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END)=tblContracts.ContractNo
    

    不过,我看不出这份案件陈述书会有什么作用。..如果@ContractNo=0或不是,则返回相同的内容。..

    正确的语法是:

      Select...
      ...
      Where(
        Case
          When <Condition>
            Then <Return if true>
            Else <Return if false>
          End
     ) = <Whatever is being matched to the output of the case statement>
    

    不管语法如何,你的例子都没有多大意义,如果你正在寻找所有匹配或合同编号为0的项目,那么你会这样做:

    Select...
    ...
    Where (
      @ContractNo = 0 Or
      @ContractNo = tblContracts.ContractNo
    )
    

    这似乎比你试图使用case语句的目的更有意义。

    编辑: 我一定有点误读了这个问题——缺少的参数通常意味着参数(在本例中为@ContractNo)没有在查询/过程的范围内声明。但有人已经指出了这一点,所以我不能因此而受到任何赞扬。

        7
  •  1
  •   Tom H zenazn    16 年前

    case语句的原因,包括整个“如果它是0,则给出参数,否则,只给出参数”,是为了测试它以尝试正确的语法。最初,我试着说“如果它是0,那么传入'%',以返回每个值。我在那里发布的代码是因为我一直收到'无效参数',并认为我的语法一定有问题。当我像这样将其分为基本参数匹配时,

    WHERE @ContractNo = tblContracts.ContractNo
    

    它很好地恢复了记录。让我再解释一下。

    我从一堆不同的表中提取信息,并用select语句中未包含的信息过滤内容(即tblContracts没有select从中提取的信息,它只在Where中使用)。用户将从一个组合框中选择,该组合框将具有不同的合同编号以及默认值“全部”。

    当组合框的索引发生变化时,我将举办一个活动。如果它是“All”,则0将作为参数传递,我不希望进行任何筛选。否则,我只需要该合同号的信息(Else@ContractNo的原因)。

        8
  •  0
  •   Richard L    17 年前

    你不是这个意思吗?

    SELECT * 
        FROM tblContracts
        WHERE     
        CASE 
           WHEN tblContracts.ContractNo = 0 THEN @ContractNo 
           ELSE tblContracts.ContractNo
        END = tblContracts.ContractNo
    

    其中@ContractNo是与tblContracts具有相同数据类型的变量。合同编号

        9
  •  0
  •   Eppz    17 年前

    为什么你甚至需要一份案件陈述?

    WHen@合同编号=0,则(0=tbl合同。合同编号) else@合同号然后(@合同号=tbl合同号)

    这没有意义,因为你可以简单地写为

    其中@contractNo=tblContracts.contractNo

        10
  •  0
  •   Tom H zenazn    17 年前

    合同编号实际上是一个数字,还是一个总是碰巧是数字的字符串。检查表和参数以及CASE语句之间的数据类型(例如,“=0”或“='0'”)

        11
  •  0
  •   JosephStyons    17 年前

    这种语法应该有效(在Oracle中是有效的)

    WHERE CASE WHEN tblContracts.ContractNo = 0 
               THEN @ContractNo 
               ELSE tblContracts.ContractNo
          END = tblContracts.ContractNo
    
        12
  •  0
  •   Richard L    17 年前

    当你说:

    我从一堆不同的表中提取信息,并用select语句中未包含的信息过滤内容(即tblContracts没有select从中提取的信息,它只在Where中使用)。用户将从一个组合框中选择,该组合框将具有不同的合同编号以及默认值“全部”。

    那么在我看来,应该有一个“存在”条款。既然你没有从那张桌子里拿出任何信息?!