SQL Server中可以为空的BIT值有3个可能的值:null,0和1.我有两列都是可以为空的BIT,我想知道它们在“NULL”的意义上何时“相等”等于“a NULL和1等于1,0不等于”NULL。但是,我所有的CASE陈述都未能给出我想要的答案。准确地进行这种比较的最佳方法是什么?
DECLARE @BitComparison TABLE
(
OldValue BIT,
NewValue BIT,
ActuallyEqual VARCHAR(10)
)
INSERT INTO @BitComparison (OldValue, NewValue, ActuallyEqual)
VALUES
(null,null,'equal'),
(null,0,'not equal'),
(null,1,'not equal'),
(0,null,'not equal'),
(0,0,'equal'),
(0,1,'not equal'),
(1,null,'not equal'),
(1,0,'not equal'),
(1,1,'equal')
SELECT *
, CASE WHEN OldValue <> NewValue then 'not equal' else 'equal' end as 'ComparisonTestA'
, CASE WHEN ISNULL(OldValue, 0) <> ISNULL(NewValue, 0) then 'not equal' else 'equal' end as 'ComparisonTestB'
, CASE WHEN ISNULL(OldValue, -1) <> ISNULL(NewValue, -1) then 'not equal' else 'equal' end as 'ComparisonTestC'
FROM @BitComparison
根据上面的脚本,硬编码的ActuallyEqual列中的值都不匹配ComparisonTest列中的值。我可以将哪些内容添加到SELECT中以动态匹配ActuallyEqual列?
答案 0 :(得分:3)
使用IS NULL
进行NULL
检查
CASE
WHEN OldValue = NewValue
OR ( OldValue IS NULL AND NewValue IS NULL ) THEN 'equal'
ELSE 'not equal'
END AS 'ComparisonTestA'
答案 1 :(得分:2)
已发布的解决方案是我能想到的最简单的解决方案。这是一个小小的变化:
CASE WHEN OldValue = NewValue
OR ISNULL(NewValue, OldValue) IS NULL THEN 'Equal' ELSE 'Not Equal' END
但我想补充说明为什么你的每个表达都不起作用
CASE WHEN OldValue <> NewValue THEN 'not equal' ELSE 'equal' END
因NULL <> Anything
而失败,因为NULL
因此当任一值为NULL
时,它将落入ELSE
语句并返回equal
。
CASE WHEN ISNULL(OldValue, 0) <> ISNULL(NewValue, 0) THEN 'not equal' ELSE 'equal' END
当其中任何一个值为NULL
时,它会被替换为0,因此当一个值为NULL
而另一个为0
时,这两个值将被识别为匹配
CASE WHEN ISNULL(OldValue, -1) <> ISNULL(NewValue, -1) THEN 'not equal' ELSE 'equal' END
这看起来应该有效,但由于ISNULL
将返回第一个参数的数据类型,-1
将转换为1
(可以看到SELECT CONVERT(BIT, -1)
1}}),因此当一个值为1而另一个为null时,这将错误地识别匹配。
考虑到这一点,您还可以将ISNULL
换成COALESCE
:
CASE WHEN COALESCE(OldValue, -1) = COALESCE(NewValue, -1) THEN 'equal' ELSE ' not equal' END
由于COALESCE
将返回具有最高优先级(INT > BIT
)的数据类型,而不是第一个参数的数据类型。
答案 2 :(得分:2)
使用 CONCAT(),这是一个有趣的选择。
SELECT OldValue,NewValue,ActuallyEqual
, Test = IIF(concat(OldValue,'-',NewValue) = concat(NewValue,'-',OldValue),'equal','not equal')
FROM @BitComparison
返回
OldValue NewValue ActuallyEqual Test
NULL NULL equal equal
NULL 0 not equal not equal
NULL 1 not equal not equal
0 NULL not equal not equal
0 0 equal equal
0 1 not equal not equal
1 NULL not equal not equal
1 0 not equal not equal
1 1 equal equal