带有一些NULL值的条件化WHERE情况

时间:2014-02-04 23:55:34

标签: sql sql-server tsql null where

下面的简化代码不会返回field1中带NULL的行(与field2,field3相同)。我可以在等号后更改任何内容,如果需要可以更改等号,但是WHERE field1之前的所有内容都应保持不变。

如何在同一案例中提取is null行?实际查询很大并且已经在三个begin..end块中,所以我真的不想通过将3个块乘以更多来进一步复杂化。对于(ALL)我想要所有行和对于(x)我希望特定值加上空值和数据将等于变量中的任何行。

declare @var1 varchar(100)
declare @var2 varchar(100)
declare @var3 varchar(100)

set @var1 = '(ALL)'
set @var2 = '(x)'
set @var3 = 'data'

SELECT *
FROM table 
WHERE
    field1 = CASE @var1 WHEN '(ALL)' THEN field1 
                        WHEN '(x)' THEN (x & nulls) 
                        ELSE @var1 
             END 
    AND field2 = CASE @var2 WHEN '(ALL)' THEN field2 
                            WHEN '(x)' THEN (x & nulls) 
                            ELSE @var2 
                 END 
    AND field3 = CASE @var3 WHEN '(ALL)' THEN field3 
                            WHEN '(x)' THEN (x & nulls) 
                            ELSE @var3 
                 END 

我真的需要说明整个WHERE行,有没有办法做到这一点?

WHERE CASE @var1 WHEN '(x)' THEN field1 = @var1 or field1 is null
编辑:我开发了一个有效的解决方案!问题是WHERE子句需要一个赋值,它不能只是一个直接的CASE,所以我们将实现一个伪真/假赋值。对@ var2 / field2和@ var3 / field3使用类似的代码。希望此解决方案能够在未来帮助其他人。谢谢你们这个伟大的网站!

SELECT * FROM table WHERE
1 = CASE WHEN @var1 = '(ALL)' THEN 1
         WHEN @var1 = '(x)' AND (field1 = @var1 OR field1 IS NULL) THEN 1
         WHEN @var1 = field1 THEN 1
         ELSE 0 END

编辑:如果你真的想要压缩它:( field1 = @ var1由最后的WHEN条件处理)

SELECT * FROM table WHERE
1 = CASE WHEN @var1 = '(ALL)' THEN 1
         WHEN @var1 = '(x)' AND field1 IS NULL THEN 1
         WHEN @var1 = field1 THEN 1
         ELSE 0 END

2 个答案:

答案 0 :(得分:0)

将WHERE子句重写为以下内容:

WHERE
    (@var1 in ('(ALL)','(x)') OR field1 = @var1)
AND (@var2 in ('(ALL)','(x)') OR field2 = @var2)
AND (@var3 in ('(ALL)','(x)') OR field3 = @var3)

答案 1 :(得分:0)

根据之前的答案和评论,您正在寻找类似的内容:

SELECT *
FROM table 
WHERE
(@var1 = '(ALL)' OR (@var1 ='(x)' AND IsNull(field1, '(x)') = @var1) OR field1 = @var1)
AND (@var2 = '(ALL)' OR (@var2 ='(x)' AND IsNull(field2, '(x)') = @var2) OR field2 = @var2)
AND (@var3 = '(ALL)' OR (@var3 ='(x)' AND IsNull(field3, '(x)') = @var3) OR field3 = @var3)
AND ...

如果给定的'x'可以是任何字符序列,您将需要这样的内容:

SELECT *
FROM table 
WHERE
(@var1 = '(ALL)' OR (@var1 like '(%)' AND IsNull(field1, SUBSTRING(@var1,2,LEN(@var1)-2)) = SUBSTRING(@var1,2,LEN(@var1)-2)) OR field1 = @var1)
AND (@var2 = '(ALL)' OR (@var2 like '(%)' AND IsNull(field2, SUBSTRING(@var2,2,LEN(@var2)-2)) = SUBSTRING(@var2,2,LEN(@var2)-2)) OR field2 = @var2)
AND (@var3 = '(ALL)' OR (@var3 like '(%)' AND IsNull(field3,SUBSTRING(@var3,2,LEN(@var3)-2)) = SUBSTRING(@var3,2,LEN(@var3)-2)) OR field3 = @var3)

为了结束我的第二个答案,我建议扩展完整代码以获得更多可读性:

declare @var1 varchar(100)
declare @var2 varchar(100)
declare @var3 varchar(100)

set @var1 = '(ALL)'
set @var2 = '(x)'
set @var3 = 'data'

declare @var1Inner varchar(100)
declare @var2Inner varchar(100)
declare @var3Inner varchar(100)

declare @var1withNull bit
declare @var2withNull bit
declare @var3withNull bit

SELECT @var1withNull = 0, @var2withNull = 0, @var3withNull = 0
IF (@var1 like '(%)') BEGIN
    SELECT @var1withNull = 1, @var1Inner = SUBSTRING(@var1,2,LEN(@var1)-2)
END
IF (@var2 like '(%)') BEGIN
    SELECT @var2withNull = 1, @var2Inner =  SUBSTRING(@var1,2,LEN(@var1)-2)
END
IF (@var3 like '(%)') BEGIN
    SELECT @var3withNull = 1, @var3Inner = SUBSTRING(@var3,2,LEN(@var3)-2)
END

SELECT *
FROM table 
WHERE (@var1 = '(ALL)' OR (@var1withNull = 1 AND IsNull(field1,@var1withNull) = @var1withNull) OR field1 = @var1)
AND (@var2 = '(ALL)' OR (@var2withNull = 1 AND IsNull(field2,@var2withNull) = @var2withNull) OR field2 = @var2)
AND (@var3 = '(ALL)' OR (@var3withNull = 1 AND IsNull(field3,@var3withNull) = @var3withNull) OR field3 = @var3)