14

所以,今天早上我问了一个问题,我没有正确表达,所以我得到了很多关于为什么 NULL 与任何东西相比都会给出 NULL/FALSE 的回答。

我的实际问题是,db 家伙测试两个可以为 NULL 的列的不等式的历史悠久的方式是什么。我的问题与这个问题完全相反。

要求如下,A 和 B 是两列:
a) 如果 A 和 B 都为 NULL,则它们相等,返回 FALSE
b) 如果 A 和 B 都不是 NULL,则返回 A<>B
c) 如果有任何一个A 或 B 为 NULL,它们不相等,返回 TRUE

4

9 回答 9

10

根据列的数据类型和可能的值:

COALESCE(A, -1) <> COALESCE(B, -1)

诀窍是找到一个永远不会出现在您的数据中的值(这里我使用了 -1)。

另一种方法是:

(A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)

这可能是一个问题,具体取决于您的特定 RDBMS 如何处理 NULL。根据 ANSI 标准,这应该给你你想要的,但无论如何谁遵循标准。:)

PS - 我还应该指出,使用 COALESCE 函数可能会使在比较列时使用索引无效。检查您的查询计划和查询性能,看看是否有问题。

PPS - 我刚刚注意到 OMG Ponies 提到 Informix 不支持 COALESCE。我相信这是一个 ANSI 标准函数,但请参阅我上面所说的关于标准的内容......

于 2009-12-02T20:29:51.213 回答
3

我会亲自写出您想出的表达式,特别是如果表预计会变大。将列包装在函数调用中会损害性能,因为这样引擎就不能使用这些列上的任何索引。当然,在一个小表中,这可能不是任何问题,但我仍然喜欢以明确的方式进行操作,以防表最终增长。

于 2009-12-02T20:32:06.220 回答
1

你可以在informix中尝试这样的事情吗?

CASE
    WHEN a IS NULL AND B IS NULL THEN false 
    WHEN a IS NULL OR B IS NULL THEN true
    ELSE a <> B
END

来自IBM Informix Guide to SQL: Syntax , CASE Expressions

于 2009-12-02T20:39:02.933 回答
0

如果您想确定如何处理 NULL,则必须使用 Informix 支持的任何东西来进行 null 检查。我没有出现太多,除了 SE 版本不支持 COALESCE,但它确实支持 DECODE,可能还支持 CASE。

WHERE COALESCE(t.a, 0) != COALESCE(t.b, 0)
WHERE DECODE(NULL, 0, t.a) != DECODE(NULL, 0, t.b)
于 2009-12-02T20:30:01.043 回答
0

对于 SQL Server,请使用:

WHERE ISNULL(A, '') <> ISNULL(B, '')
于 2009-12-02T20:34:08.727 回答
0

问题是a<>b(或a=b)产生NULL,而不是10当一个或两个操作数为 NULL 时。这对于这种情况无关紧要,=因为NULL OR 1is1NULL OR 0isNULL的行为类似于在子句0中进行选择。WHERE

你可以说:

a<>b OR (a IS NULL)<>(b IS NULL)

但是,无论哪种方式都需要这样做,这可能表明您正在滥用 NULL,并且应该考虑更改架构以使用其他一些 NOT NULL 值来表示这种可比较的条件。

例如,如果您有一个包含列的persontitle,请不要使用 NULL 来表示它们没有标题;这不是一个“缺失”的数据,只是不存在标题。因此,将其存储为一个空字符串'',您可以愉快地与其他空字符串进行比较。(好吧,除非你当然运行 Oracle,但它的空字符串问题......)

于 2009-12-02T21:06:23.450 回答
0

IBM Informix Dynamic Server 出于各种历史(又名“坏”)原因对布尔值有一些特殊的看法。适应@astander 提出的想法,这个 CASE 表达“有效”,但我会是第一个说“不明显”的人(见 - 我在你之前说过!)。设置阶段:

create table x(a int, b int);
insert into x values(null, null);
insert into x values(null, 1);
insert into x values(1, null);
insert into x values(1, 1);
insert into x values(1, 2);

选择语句:

SELECT *
  FROM x
  WHERE   CASE
          WHEN a IS NULL AND b IS NULL THEN 'f'::BOOLEAN
          WHEN a IS NULL OR  b IS NULL THEN 't'::BOOLEAN
          WHEN a != b                  THEN 't'::BOOLEAN
          ELSE                              'f'::BOOLEAN
          END
;

此查询的结果是:

                 1
      1           
      1          2

问题:

  • IDS 不将 FALSE 或 TRUE 或 UNKNOWN 识别为关键字。
  • IDS 不能识别布尔表达式,例如 'a != b'(或 'a <> b')。

是的,不得不说这一点让我非常痛苦。

于 2009-12-03T00:56:47.550 回答
0

如果

where ((A=B) OR (A IS NULL AND B IS NULL))

是为了平等,那为什么不使用:

where NOT (
  ((A=B) OR (A IS NULL AND B IS NULL))
)

不平等?

于 2016-02-04T19:06:52.547 回答
0

@user3830747 答案的轻微修改,基于德摩根定律

NOT (NVL(a = b,FALSE) OR COALESCE(a,b) IS NULL)

于 2021-04-28T18:10:27.690 回答