19

我很难找出比 SQL 语句更大的值。

这是我的代码:

select one, two three from orders
where case when @orderid > 0 then orders.orderid = @orderid end

@orderid 是传递给存储过程的参数。这个想法是,如果传递了一个有效的 (> 0) orderid,则将其用作 where 子句中的过滤器,否则不要全部使用它。

4

5 回答 5

23

Guffa 有正确的答案,但是您使用 CASE 技巧(偶尔会派上用场)执行此操作的方式是:

--If order ID is greater than 0, use it for selection
--otherwise return all of the orders.
select one, two, three
from orders
where orders.orderid = CASE
    WHEN @orderid > 0 then @orderid
    ELSE orders.orderid
END

CASE 总是要返回一些东西,所以如果你想有条件地在 WHERE 子句中“禁用”一个语句并且不能使用 OR,你可以将这个东西设置为等于它本身,并且应该始终为 true(比较空值时除外)。

编辑:我还应该说,在这样的查询中,可以返回的行数可能会有很大差异(一行与整个表),使用 OPTION (RECOMPILE) 提示可能有助于提高单行情况下的性能.

于 2013-09-22T01:24:30.070 回答
4

NYCDotnet 答案,就像这里的其他答案一样有效,但它们可能不是SARGable

要进行此非 SARGable 查询..

select one, two three from orders
where 
     case 
     when @orderid > 0 then orders.orderid  
     else 0
     end = @orderid

..SARGable,改为这样做:

select one, two three from orders
where 
     @orderid > 0 and orders.orderid = @orderid

     or not (@orderid > 0)

如果@orderid 永远不会变成负数,只需使解决方案更简单:

select one, two three from orders
where 
     @orderid > 0 and orders.orderid = @orderid

     or @orderid = 0

或者更好,即如果@orderid 不会变成负数:

select one, two three from orders
where 
     @orderid = 0

     or orders.orderid = @orderid
于 2013-09-22T01:59:51.880 回答
3

你不需要在CASE这里使用。同样的逻辑,重新排列一下:

select one, two three from orders
where @orderid is null or @orderid <= 0 or orders.orderid = @orderid
于 2013-09-22T01:12:15.800 回答
3

您不能将条件用作case表达式中的值。

您可以只使用or运算符使条件不用于无效值:

select one, two, three from orders
where @orderid <= 0 or orders.orderid = @orderid
于 2013-09-22T01:12:58.863 回答
0
IF @orderid < 0
   BEGIN
      RETURN
   END

  SELECT one, two, three 
  FROM orders 
  WHERE orders.orderid = @orderid 

事实上,因为 id 是一个 int 并且如果它是一个标识列,它总是大于零,所以你甚至不需要检查@orderid 是否大于零。话虽如此,上面的代码将阻止查询以无效的订单 ID 运行。

你也可以这样做

SELECTone, two, three

FROM orders

WHERE orderid = @orderid AND @orderid > 0
于 2013-09-22T01:26:05.110 回答