【问题标题】:Usage of case clause in where clause在 where 子句中使用 case 子句
【发布时间】:2016-03-24 05:23:25
【问题描述】:

我需要根据下拉列表值向存储过程添加过滤器

可用值为 0,1,2,3,4,5。 @TescilDurum 是我的参数。

0 = ALL
1 = TescilDurumId IN 4 OR 5
2 = t.ID IS NULL
3 = dncts.RegistrationCode IS NULL
4 = hsm.ID IS NULL AND dncts.RegistrationCode IS NULL IS NOT NULL
5 = hsm.ENSMRN IS NULL

到目前为止,我从互联网上的一个类似问题答案中尝试过这个,但我不确定这是否是正确的做法。我不确定这种“反向逻辑”是否是正确的方法。并且 order by after 它也给出了错误...

AND 1 =
    CASE WHEN @TescilDurum = 1 AND t.TescilDurumId NOT IN (4,5) THEN 0 
    ELSE CASE WHEN @TescilDurum = 2 AND t.Id IS NOT NULL THEN 0
    ELSE CASE WHEN @TescilDurum = 3 AND hsm.EnsMRN IS NOT NULL THEN 0
    ELSE CASE WHEN @TescilDurum = 4 AND hsm.Id IS NOT NULL AND dncts.RegistrationCode IS NULL THEN 0
    ELSE CASE WHEN @TescilDurum = 5 AND hsm.EnsMRN IS NOT NULL THEN 0
    ELSE 1 END

【问题讨论】:

  • 所有使用ELSE CASE的地方都是多余的。 case 语句在 SQL 中每个 WHEN 部分的工作方式与其他语言中的“elseif”相同。

标签: sql-server tsql sql-server-2008-r2 case where-clause


【解决方案1】:

你可以简化它:

WHERE 
  (CASE 
       WHEN @TescilDurum = 0 THEN 1
       WHEN @TescilDurum = 1 AND TescilDurumId IN (4,5) THEN 1
       WHEN @TescilDurum = 2 AND t.ID IS NULL THEN 1
       WHEN @TescilDurum = 3 AND dncts.RegistrationCode IS NULL THEN 1
       WHEN @TescilDurum = 4 AND hsm.ID IS NULL AND dncts.RegistrationCode IS NOT NULL THEN 1
       WHEN @TescilDurum = 5 AND hsm.ENSMRN IS NULL THEN 1
       ELSE NULL    -- this is default and can be skipped if needed
  END) = 1

编辑:

对于那些害怕上面的查询总是1 = 1的人:

CASE 具有默认的ELSE NULL 子句,因此当整个语句之前没有匹配时,将返回NULLNULL = 1 => NULL

DECLARE @v INT = 4;

SELECT 1
WHERE(CASE WHEN @v = 1 THEN 1
           WHEN @v = 2 THEN 1
           WHEN @v = 3 THEN 1
           ELSE NULL    -- this is default and can be skipped if needed
      END) = 1
 -- empty resultset

和:

CREATE TABLE #tab(ID INT, col VARCHAR(100));

INSERT INTO #tab
VALUES (1, 'aa'), (2, 'bbb'), (3, NULL), (4, 'aa');

-- DROP DOWN MENU
-- 1 all records
-- 2 only those which ID is in (2,3)
-- 3 only those which has col = 'aa'
-- 4 only those which has NULL value in col

DECLARE @variable INT = 3;

SELECT *
FROM #tab
WHERE 
(
  CASE WHEN @variable = 1 THEN 1
       WHEN @variable = 2 AND ID IN (2,3) THEN 1
       WHEN @variable = 3 AND col = 'aa'  THEN 1
       WHEN @variable = 4 AND col IS NULL THEN 1
       ELSE NULL    -- this is default and can be skipped if needed
 END
) = 1

请记住,AND 存在复合条件,因此将返回正确的行。

LiveDemo

【讨论】:

  • 看起来很整洁,但会出现一些错误,例如“CASE @TescilDurum”会给出“在预期条件的上下文中指定的非布尔类型的表达式”错误。还有一些看起来很正常的不正确的语法错误:(
  • @lad2025 只是一个问题,为什么逻辑不直接是 1=1,这是每个案例都指向我的?
  • @brykneval 有默认的ELSE NULL 所以NULL = 1 => NULL
  • @lad2025 好的,但是 OP 值是 0,1,2...5 并且每个可能都会生成 1?可以吗?
  • @brykneval 绝对。请记住,@TescilDurum 一次只能保存一个值。所以用户只能从1-5 范围内得到一个
猜你喜欢
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 1970-01-01
  • 2013-10-16
  • 2017-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多