我需要在值和之前的值之间进行大量的比较。
例如:ReceivedBy
和PreviousReceivedBy
。
我开始时:
WHERE ReceivedBy != PreviousReceivedBy
但是如果任何一个值为null,则返回false,(当我真的需要它为真时)。所以我把它更新为:
WHERE ReceivedBy != PreviousReceivedBy
OR (ReceivedBy IS NULL AND PreviousReceivedBy IS NOT NULL)
OR (ReceivedBy IS NOT NULL AND PreviousReceivedBy IS NULL)
这很好用,但我有一大堆需要比较的字段。我想找到一种方法来用较少的代码进行比较(不关闭ANSI_NULLS
)。
显然如果没有别的办法,那么我只需要输入所有3行进行比较。
更新:
作为一个例子,这是我希望的
ReceivedBy = 123
PreviousReceivedBy = 123
Result = FALSE
ReceivedBy = 5
PreviousReceivedBy = 123
Result = TRUE
ReceivedBy = NULL
PreviousReceivedBy = 123
Result = TRUE
ReceivedBy = 123
PreviousReceivedBy = NULL
Result = TRUE
ReceivedBy = NULL
PreviousReceivedBy = NULL
Result = FALSE
答案 0 :(得分:2)
如果两列都是varchar
s,我会选择以下内容:
coalesce(ReceivedBy, 'NULL') != coalesce(PreviousReceivedBy, 'NULL')
如果它们是整数,我会将一些值大大低于零(以明确表示null
值)而不是'NULL'
。
从列的名称我假设它必须是字符串值或整数值:)
<强>更新强>
正如@Siyual指出的那样,替换字符串应该是&#34;在可能性范围之内&#34;,你应该将'NULL'
替换为一些非字母字符,如'#'
: )
答案 1 :(得分:2)
另一种不重复数据的方法是使用COALESCE
Where ReceivedBy != PreviousReceivedBy
And Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null
NULL
不能等同于任何内容,甚至不能等同于NULL
,因此,如果任何值为NULL
,则ReceivedBy != PreviousReceivedBy
将评估为真。
其次,如果两个值均为NULL
,则Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null
将评估为false,从而强制对其进行过滤。
如果两者都不是NULL
,那么第一个条件如果相等就会失败。
不可否认,这并没有节省太多代码,但这是一种改进。
这可以很容易地分组在括号中,并复制/面食,以便您检查所有剩余的字段。
Where (ReceivedBy != PreviousReceivedBy And Coalesce(ReceivedBy, PreviousReceivedBy) Is Not Null)
And[Or] (Foo != Bar And Coalesce(Foo, Bar) Is Not Null)
...
答案 2 :(得分:1)
在与可为空的值进行比较时,我遇到了同样的问题,NULL
总是返回unknown
,直到我们只在TRUE
或FALSE
之间我们想要的距离为止>
最后,我声明了一个标量值函数,这些逻辑像other SQL(s)这样将NULL处理为
普通比较运算符产生null(表示“未知”),而不是 当任一输入为null时为true或false。例如,7 = NULL产生 null,7 <> NULL也是如此。如果此行为不合适,请使用 是[不是]与构造不同:
a IS DISTINCT FROM b => a != b
a IS NOT DISTINCT FROM b => a == b
a IS NOT DISTINCT FROM b
could be rewritten为
(a IS NOT NULL AND b IS NOT NULL AND a=b) OR (a IS NULL AND b is NULL)
我将sql_variant用于以下基本参数:int,datetime,varchar,...
create function IsEqual(
@a sql_variant,
@b sql_variant
)
returns bit
as
begin
return (CASE WHEN (@a IS NOT NULL AND @b IS NOT NULL AND @a=@b) OR (@a IS NULL AND @b is NULL) THEN 1 ELSE 0 END);
end
create function IsNotEqual(
@a sql_variant,
@b sql_variant
)
returns bit
as
begin
return 1-dbo.IsEqual(@a,@b);
end
使用
select dbo.IsEqual(null, null) Null_IsEqual_Null,
dbo.IsEqual(null, 1) Null_IsEqual_1,
dbo.IsEqual(1, null) _1_IsEqual_Null,
dbo.IsEqual(1, 1) _1_IsEqual_1,
dbo.IsEqual(CAST('2017-08-25' AS datetime), null) Date_IsEqual_Null,
dbo.IsEqual(CAST('2017-08-25' AS datetime), CAST('2017-08-25' AS datetime)) Date_IsEqual_Date
针对您的情况
select dbo.IsNotEqual(123,123) _123_IsNotEqual_123,
dbo.IsNotEqual(5,123) _5_IsNotEqual_123,
dbo.IsNotEqual(Null,123) Null_IsNotEqual_123,
dbo.IsNotEqual(123,Null) _123_IsNotEqual_Null,
dbo.IsNotEqual(Null,Null) Null_IsNotEqual_Null
答案 3 :(得分:1)
(NULLIF(@a, @b) IS NOT NULL)
的意思是"@a != @b
,即使其中之一或两者均为空。
答案 4 :(得分:1)
WHERE ISNULL(ReceivedBy, -1) != ISNULL(PreviousReceivedBy, -1)
假设列永远不会有负值