切换案例/如果在where子句中

时间:2011-05-27 14:53:51

标签: sql sql-server sql-server-2005 tsql stored-procedures

我试图根据某些价值改变某个地方的条件。我在这里看过类似的文章,包括:

SQL Switch/Case in where clause

但他们并没有完全处理我的案子。

我所拥有的是一个基于其输入执行选择的存储过程。这些输入是可选的(或者具有默认参数,因为他们更愿意调用它)。

所述参数中有2个是数字。

  • 如果仅指定了第一个数字,则列X必须等于该数字。
  • 如果指定了第一个和第二个数字,那么第X列必须是> =到第一个AND< =到第二个。
  • 如果只指定了第二个号码,则为无效。

这是我尝试的(显然不起作用)

DECLARE @SECOND INT;
DECLARE @FIRST INT;

SET @FIRST = 123456;
SET @SECOND = 67890;

SELECT * FROM BANK_DETAIL 
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    CASE
        WHEN @SECOND IS NULL THEN 
            X = @FIRST
        ELSE 
            X >= @FIRST AND X <= @SECOND 
    END
        -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY X

真的这感觉它需要一个IF / ELSE而不是CASE但是我被引导到CASE .....

哦,这是MS SQL&gt; = 2005

5 个答案:

答案 0 :(得分:4)

尝试调整@SECOND的无效性,而不是使用CASE。

SELECT *
FROM BANK_DETAIL
WHERE
-- other conditions go here
AND ((@SECOND IS NULL AND X = @FIRST)
  OR (@SECOND IS NOT NULL AND X >= @FIRST AND X <= @SECOND))

答案 1 :(得分:3)

SELECT * FROM BANK_DETAIL 
WHERE
    (@SECOND IS NULL AND X = @FIRST) or
    (X >= @FIRST AND X <= @SECOND)

虽然做得更有效率:

IF @SECOND IS NULL
BEGIN
   SELECT * FROM BANK_DETAIL 
   WHERE
     X = @FIRST
END
ELSE
BEGIN
   SELECT * FROM BANK_DETAIL 
   WHERE
     X >= @FIRST AND X <= @SECOND
END

答案 2 :(得分:2)

我会使用布尔运算符:

SELECT * FROM BANK_DETAIL 
WHERE
  ((@SECOND IS NULL AND X = @FIRST) OR 
  (@SECOND IS NOT NULL AND X >= @FIRST AND X <= @SECOND));

答案 3 :(得分:1)

您正在构建dynamic search condition。通过强制一个语句来覆盖两个情况,您正在削减优化器选项。当@seconds为null且when不为null时,生成的计划必须在两个情况下工作。使用两个单独的声明你会好得多:

IF @SECOND IS NULL THEN
   SELECT * FROM BANK_DETAIL 
   WHERE  X = @FIRST
   ORDER BY X
ELSE
   SELECT * FROM BANK_DETAIL 
   WHERE X >= @FIRST AND X <= @SECOND 
   ORDER BY X

你直觉“简化”成一个单一的陈述会导致你走错路。结果是文本较少,但由于计划欠佳,执行时间要长得多。在我的回答开始时链接的文章详细介绍了这一主题。

答案 4 :(得分:0)

问题是CASE返回一个值,它不是逻辑中的一个分支。 OMG提供的链接几乎是这个链接的权威来源(几乎任何来自Erland Sommarskog的建议都是很好的建议)。

链接的快速摘要:

您可以使用动态SQL,根据条件构建语句。这通常是性能最佳的方法,但也有缺点。最大的缺点之一是可能存在的安全问题,因此请确保您完全了解SQL注入攻击以及如何防止它们。

另一种方法是使用OR在WHERE语句中使用复杂逻辑。在你的情况下,它将类似于下面。这种方法比动态SQL更简单,更安全,但性能可能并不总是很好。如果你的情况表现良好(测试它),那么坚持这种方法。

SELECT
    *    -- I assume that you used * just as an example and don't actually use this in your production code
FROM
    Bank_Detail
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    (@second IS NULL AND X = @first) OR
    (@second IS NOT NULL AND (x >= @first AND x <= @second))
    -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY
    x

组织声明的另一种方式刚刚发生在我身上......

SELECT
    *
FROM
    Bank_Detail
WHERE -- POSSIBLY SOME OTHER WHERE CLAUSES
    x >= @first AND
    x <= COALESCE(@second, @first)
    -- POSSIBLY SOME MORE WHERE CLAUSES
ORDER BY
    x

我还没有测试过,但我认为这在逻辑上是等效的,可能会为您提供更一致的查询计划。

Erland还提供了其他一些可能的方法,所以一定要阅读他关于这个主题的完整文章。