在SQL WHERE中执行IF

时间:2010-01-04 16:33:52

标签: sql sql-server

我想这样做

SELECT *
  FROM sales_order_header       
 WHERE order_reference LIKE @order_reference + '%'
   AND ((@booked_in IS NULL) OR ( booked_in = @booked_in))
   AND ((@depot_assigned IS NULL) OR ( IF @depot_assigned = 'Y' depot_code <> ' ' ELSE depot_code = ' ') )

我确信你们都可以猜到OR(IF @dede_assigned等)位失败。

我该如何做这样的事情,或者我必须根据@depot_assigned参数的值将它作为两个单独的select语句来完成。

4 个答案:

答案 0 :(得分:7)

SELECT
        *

    FROM
        sales_order_header

    WHERE
        order_reference LIKE @order_reference + '%'         AND
        ((@booked_in IS NULL) OR ( booked_in = @booked_in)) AND
        ((@depot_assigned IS NULL) OR 
            ( @depot_assigned = 'Y' AND depot_code <> ' ' ) OR
            ( @depot_assigned <> 'Y' AND depot_code = ' ') )

答案 1 :(得分:3)

您正在寻找T-SQL CASE语句。对以下代码的修改应该适合您:

SELECT
    *
FROM
    sales_order_header

WHERE
    order_reference LIKE @order_reference + '%'         AND
    ((@booked_in IS NULL) OR ( booked_in = @booked_in)) AND
    ((@depot_assigned IS NULL) OR (CASE WHEN @depot_assigned = 'Y' THEN depot_code <> ' ' ELSE depot_code = ' ' END) )

答案 2 :(得分:0)

当您构建类似于您尝试的查询时,查询优化器必须创建一个计划以适合参数的任何值。这将导致最糟糕的计划。因此,即使您提出了正确的表达式(使用CASE),由于OR条件相矛盾,查询的执行性也会非常差。

将IF分成SQL条件,并对每种情况使用不同的查询:

IF @booked_in IS NULL and @depot_assigned IS NULL
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
ELSE IF @depot_assigned IS NULL
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
ELSE IF @booked_in IS NULL AND @depot_code='Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND depot_code <> ' '
ELSE IF IF @booked_in IS NULL AND @depot_code<>'Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND depot_code = ' '
ELSE IF @depot_code = 'Y'
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
  AND depot_code <> ' '
ELSE
  SELECT * FROM sales_order_header
  WHERE order_reference LIKE @order_reference + '%'
  AND booked_in = @booked_in
  AND depot_code = ' '

尽管有明显的不雅和缺乏优雅,但这是最好的方法。它的主要缺点是可维护性问题,并且在使用动态SQL构建查询时有一个可行的替代方法。

最终,IF条件的复杂性是代码味道,您的数据访问API会执行太多应该是单独的API入口点的事情。

答案 3 :(得分:0)

SELECT * FROM sales_order_header       
WHERE 
order_reference LIKE @order_reference + '%'
AND 
booked_in = ISNULL(@booked_in,booked_in)
AND 
CASE 
    WHEN @depot_assigned IS NULL THEN 1 
    WHEN @depot_assigned  = 'Y' AND depot_code <> ' ' THEN 1 
    WHEN @depot_assigned <> 'Y' AND depot_code  = ' ' THEN 1
    ELSE 0 
END = 1

编辑:与其他一些答案类似。稍微简化一下。