NULL 时的计算字段

Ben*_*Coo 2 null sql-server t-sql computed-column

我的表中有两个字段:A int, B int。我想添加两个使用这两个字段& 的计算字段 ( CF1& CF2) 。AB

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或者BNULL,无论CF1CF2也应该是NULL

换句话说:应该只有在0,1或3的值CF1CF2如果有一个值NOT NULL在字段AB

+------+------+------+------+
|  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)

ype*_*eᵀᴹ 7

首先,让我解释一下为什么你的代码不能正常工作时,A或者BNULL通过格式化你的代码,以证明你有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 = BA is nullor B is null

所以要解决这个问题,你需要明确的比较A = B或比较ABNULL, 来区分。因此,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)


Mar*_*ith 6

您也可以完全不加任何CASE表情地执行此操作。

SIGN功能

返回指定表达式的正 (+1)、零 (0) 或负 (-1) 符号。

并返回NULLNULL输入

如果您可以使用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)