Where 子句中使用 Like 运算符的 CASE 语句

CASE Statement in Where clause using Like Operator

我在 where 子句中使用 CASE 表达式时遇到问题,据我所知,语法是正确的,但出现错误。下面是我的代码:

Where
CASE 
            WHEN (@ItemFor='' and @ItemTo='')
            THEN id like '%'
            ELSE id between @ItemFor and @ItemTo
        END

上面的代码在我看来是正确的,但我收到语法错误

Incorrect syntax near the keyword 'like'.

编辑

我有4组参数,都需要去where子句,都是字符串值:

WHERE

        CASE 
            WHEN (@ItemFor='' and @ItemTo='')
                THEN id like '%'
                ELSE id between @ItemFor and @ItemTo
        END
    AND 
        CASE 
            WHEN (@CodeFrom='' and @CodeTo='')
            THEN Code like '%'
            ELSE code between @CodeFrom and @CodeTo
        END

您不需要 case 表达式。只要做:

where ((@ItemFor = '' and @ItemTo = '') or
       id between @ItemFor and @ItemTo
      )

您的版本不工作,因为SQL服务器没有布尔变量。您的 case 表达式试图 return 布尔表达式,但这样的表达式不是值。

顺便说一句,您可能打算:

where (id >= @itemfrom or @itemfrom = '') and
      (id <= @itemto or @itemto = '')

这允许您仅设置一个限制。

因为 CASE 不能 return 布尔值,你必须 return 其他东西并比较:

WHERE
  CASE
    WHEN Condition1 THEN 1
    WHEN Condition2 THEN 0
    WHEN Condition3 THEN 1
    ELSE 0
  END = 1

试试这个方法。

where (@itemFor='' and @itemto='') OR (id between @itemFor and @itemto)

与您的 case case 语句相同。如果两个变量都为空,则不要过滤 ID 子句。如果填充了变量,请检查范围内的 ID

注意,如果你做多个条件,我会建议添加额外的括号,例如

where ( (@itemFor='' and @itemto='') OR (id between @itemFor and @itemto) )
   and (firstName like '%JOE%')

等等

试试这个:

WHERE

CASE 
    WHEN (@ItemFor='' AND @ItemTo='') THEN 1
    WHEN (id between @ItemFor and @ItemTo) THEN 1
    WHEN (@CodeFrom='' and @CodeTo='') THEN 1
    WHEN (code between @CodeFrom and @CodeTo) THEN 1
    ELSE 0
END = 1

我猜你的错误区域

WHERE

    CASE 
        WHEN (@ItemFor='' and @ItemTo='')
            THEN id like '%'                  -------conditional operator in result
            ELSE id between @ItemFor and @ItemTo ---------- conditional operator
    END
AND 
    CASE 
        WHEN (@CodeFrom='' and @CodeTo='')
        THEN Code like '%'
        ELSE code between @CodeFrom and @CodeTo  -------------conditional operator
    END

你可以试试下面的方法

WHERE    
case when (@ItemFor='' and @ItemTo='') and id like '%' 
Then (case when id >=@ItemFor and id<=@ItemTo then id else end)
Else 
case when (@CodeFrom='' and @CodeTo='') and Code like '%' 
Then (case when code >=@ItemFor and code<=@ItemTo then code else end)
end

解释 CASE WHEN 有什么问题。

A CASE WHEN return是一个值,您可以根据不同的条件进行选择。
它 return 是一个基于匹配的第一个条件的值。
因此,它不应该 return 一个标准。

下面的示例使用了它。

WHERE
   (CASE 
    WHEN @ItemFor='' AND @ItemTo='' AND id IS NOT NULL THEN 1
    WHEN id BETWEEN @ItemFor AND @ItemTo THEN 2
    ELSE 0
    END) > 0
   AND
   (CASE 
    WHEN @CodeFor='' AND @CodeTo='' AND Code IS NOT NULL THEN 1
    WHEN Code BETWEEN @CodeFor AND @CodeTo THEN 2
    ELSE 0
    END) > 0

也就是说,关于这个例子。
在 WHERE 子句中不使用 CASE WHEN 的解决方案可能是更好的方法。

示例:

WHERE id IS NOT NULL
  AND Code IS NOT NULL
  AND ((@ItemFor='' AND @ItemTo='') OR (id BETWEEN @ItemFor AND @ItemTo))
  AND ((@CodeFor='' AND @CodeTo='') OR (Code BETWEEN @CodeFor AND @CodeTo))

因为查询优化器很难根据 CASE WHEN 选择最快的执行计划。

您可以简化并使用这个条件:

WHERE ((@ItemFor='' and @ItemTo='' AND id like '%') OR id between @ItemFor and @ItemTo)
  AND ((@CodeFrom='' and @CodeTo='' AND Code like '%') OR code between @CodeFrom and @CodeTo)

现在语法正确了。

此外,id like '%'Code like '%' 没有任何意义,因为它们始终为真。它们可以读作 "check if id (or Code) is anything",因此可以(应该)删除它们。

这可能会解决您的问题:

WHERE 
((@ItemFor = '' and @ItemTo = '' and id like '%') 
or (@ItemFor <> '' and @ItemTo <> '' and id between @ItemFor and @ItemTo))      
AND 
((@CodeFrom = '' and @CodeTo = '' and Code like '%')
 or (@CodeFrom <> '' and @CodeTo <> '' and code between @CodeFrom and @CodeTo))