Ben*_*Coo 2 null sql-server t-sql computed-column
我的表中有两个字段:A int, B int
。我想添加两个使用这两个字段& 的计算字段 ( CF1
& CF2
) 。A
B
CF1 = (case when [A]>[B] then (CF1=3) else case when [A]<[B] then (CF1=0) else (CF1=1) end end)
CF2 = (case when [A]<[B] then (CF2=3) else case when [A]>[B] then (CF2=0) else (CF2=1) end end)
Run Code Online (Sandbox Code Playgroud)
这工作正常,但是当两个字段 ( A
& B
) 是NULL
,CF1
并且CF2
是 = 1 时。如何避免这种情况?我的意思是,当领域中的任意一个A
或者B
是NULL
,无论CF1
和CF2
也应该是NULL
。
换句话说:应该只有在0,1或3的值CF1
和CF2
如果有一个值NOT NULL
在字段A
与B
。
+------+------+------+------+
| A | B | CF1 | CF2 |
+------+------+------+------+
| 2 | 3 | 0 | 3 |
| 5 | 2 | 3 | 0 |
| 2 | 2 | 1 | 1 |
| NULL | NULL | NULL | NULL |
| NULL | 1 | NULL | NULL |
| 1 | NULL | NULL | NULL |
+------+------+------+------+
Run Code Online (Sandbox Code Playgroud)
首先,让我解释一下为什么你的代码不能正常工作时,A
或者B
是NULL
通过格式化你的代码,以证明你有2个CASE
表情,一个在另一个内:
CF1 = (case
when [A]>[B] then (CF1=3)
else case
when [A]<[B] then (CF1=0)
else (CF1=1)
end
end)
Run Code Online (Sandbox Code Playgroud)
如果A > B
为真,则结果为(CF1=3)
。如果这不是真的,如果A < B
是真的,结果是(CF1=0)
。否则,如果两者A>B
都不A<B
为真,则结果为(CF1=1)
。最后一种情况(ELSE - ELSE
部分)涵盖了任何剩余的情况,这意味着 whenA = B
或A is null
or B is null
。
所以要解决这个问题,你需要明确的比较A = B
或比较A
和B
与NULL
, 来区分。因此,CASE
表达式应该有 4 个部分,而不是 3 个部分。而且(与问题无关)我们不需要两个嵌套的表达式,我们可以用一个表达式得到我们想要的结果。
而且我假设您希望结果是3, 1, etc
并且(CF1=3)
只是伪代码。
CF1 = case
when A > B then 3
when A < B then 0
when A = B then 1
else null
end
Run Code Online (Sandbox Code Playgroud)
请注意,ELSE NULL
不需要,因为它是CASE
表达式的默认值。如果你愿意,你可以对你的意图代码更加严格和清晰:
CF1 = case
when (A > B) then 3
when (A < B) then 0
when (A = B) then 1
when (A is null or b is null) then
null
else null -- 'ERROR: This should never happen'
end
Run Code Online (Sandbox Code Playgroud)
您也可以完全不加任何CASE
表情地执行此操作。
该SIGN
功能
返回指定表达式的正 (+1)、零 (0) 或负 (-1) 符号。
并返回NULL
上NULL
输入
如果您可以使用0,1,2
而不是,0,1,3
那么您可以使用1 + SIGN(A - B)
.
如果你必须有,0,1,3
那么你可以使用以下模式
+------+----------+--------------------+------------------------+
| sign | sign + 1 | Power(2, sign + 1) | Power(2, sign + 1) - 1 |
+------+----------+--------------------+------------------------+
| -1 | 0 | 1 | 0 |
| 0 | 1 | 2 | 1 |
| 1 | 2 | 4 | 3 |
+------+----------+--------------------+------------------------+
Run Code Online (Sandbox Code Playgroud)
如下
DECLARE @T TABLE (
A INT,
B INT,
cf1 AS POWER(2, SIGN(A - B) + 1) - 1,
cf2 AS POWER(2, SIGN(B - A) + 1) - 1 );
-- populate with some data
INSERT INTO @T
(A,
B)
VALUES (2,3),
(5,2),
(2,2),
(NULL,NULL),
(NULL,1),
(1,NULL);
SELECT *
FROM @T
Run Code Online (Sandbox Code Playgroud)
返回
+------+------+------+------+
| A | B | cf1 | cf2 |
+------+------+------+------+
| 2 | 3 | 0 | 3 |
| 5 | 2 | 3 | 0 |
| 2 | 2 | 1 | 1 |
| NULL | NULL | NULL | NULL |
| NULL | 1 | NULL | NULL |
| 1 | NULL | NULL | NULL |
+------+------+------+------+
Run Code Online (Sandbox Code Playgroud)