最简单的SQL表达式,用于检查两个列是否具有相同的值,并考虑NULL

最简单的SQL表达式,用于检查两个列是否具有相同的值,并考虑NULL,sql,oracle,oracle11g,null,Sql,Oracle,Oracle11g,Null,我试图找出最简单的通用SQL表达式,它可以检查a和b两列是否相同。换句话说,在以下情况下计算结果为true的表达式: a为NULL,b为NULL;或 a不是NULL和b不是NULL和a=b 假设列a和b具有完全相同的数据类型 我在下面的示例中使用的最明显的解决方案非常复杂,特别是因为我需要在一个15列的表中重复第15x条: SELECT * FROM ( SELECT 'x' a, 'x' b FROM dual UNION ALL SELECT 'x' a,

我试图找出最简单的通用SQL表达式,它可以检查
a
b
两列是否相同。换句话说,在以下情况下计算结果为
true
的表达式:

  • a
    NULL
    b
    NULL
    ;或
  • a
    不是
    NULL
    b
    不是
    NULL
    a=b
  • 假设列
    a
    b
    具有完全相同的数据类型

    我在下面的示例中使用的最明显的解决方案非常复杂,特别是因为我需要在一个15列的表中重复第15x条:

    SELECT * FROM (
    
        SELECT 'x' a, 'x' b FROM dual
            UNION ALL
        SELECT 'x' a, NULL b FROM dual
            UNION ALL
        SELECT NULL a, 'x' b FROM dual
            UNION ALL
        SELECT NULL a, NULL b FROM dual
            UNION ALL
        SELECT 'x' a, 'y' b FROM dual
            UNION ALL
        SELECT 'x' a, NULL b FROM dual
            UNION ALL
        SELECT NULL a, 'y' b FROM dual
            UNION ALL
        SELECT NULL a, NULL b FROM dual
    
    )
    
    WHERE (a IS NULL AND b IS NULL) OR
          (a IS NOT NULL AND b IS NOT NULL AND a = b)
    /
    
    预期结果是:

    +--------+--------+
    |   a    |   b    |
    +--------+--------+
    | x      | x      |
    | (null) | (null) |
    | (null) | (null) |
    +--------+--------+
    
    tl;dr-我可以简化我的
    WHERE
    子句吗(使其更紧凑,同时保持逻辑正确?

    附言:对于任何SQL纯粹主义者坚持认为“
    NULL
    不是一个值”,我一点也不在乎。出于实际目的,如果
    a
    包含
    NULL
    b
    不包含,则
    a
    b
    不同。它们是否不同并不“未知”。所以,请事先不要在那条巷子里争吵

    附言:我的SQL风格是Oracle 11g


    p.p.p.S.:有人认为这个问题是“”的重复,但粗略检查一下这个问题,就会发现答案没有贴在这个帖子上的答案有用,并且不符合我特别明确的标准。仅仅因为它们相似,并不意味着它们是重复的。我一直不明白为什么人们如此努力地把我的问题X变成其他人的问题Y。

    简单不一定是有效的

    考虑一下这种可能性

    WHERE X || 'x' = Y || 'x'
    

    如果您真的想推动信封,请使用非空的SYS\u OP\u MAP\u

    您可以将其简化为:

    WHERE (a IS NULL AND b IS NULL) OR
          (a = b)
    
    不为空
    不需要

    如果您有一个“安全”值(即从未使用过的值),您可以执行以下操作:

    WHERE COALESCE(a, ' ') = COALESCE(b, ' ')
    

    这假设
    '
    不是有效值。

    我发现Ask Tom文章最有帮助。在Oracle中,您可以使用该函数执行以下操作:

     WHERE 1 = DECODE(a, b, 1, 0)
    

    这是迄今为止我见过的最紧凑的解决方案。

    我不关心性能。我只关心表达的紧凑性。有趣。什么样的业务条件使它成为一个问题?代码的紧凑性和可读性?一种普遍倾向于简单、简洁而不是冗长、难以阅读。我想你可以有把握地假设,因为我说过紧凑性是我的目标,我对我正在处理的数据有足够的了解,所以知道
    WHERE
    子句的性能并不是什么大问题。我通常在SQL Server中使用
    ISNULL()
    函数,我认为
    NVL()
    在Oracle中是等效的,也许试着看看这个函数?NVL()不起作用。LNNVL应该有用。
    LNNVL
    这个重复的问题正是你想要的。你是对的。我瞎了(.谢谢@Noel.我没有意识到
    LNNVL
    优于
    DECODE
    ,但事实确实如此。我刚刚对我自己的问题投了赞成票:)第一个肯定更好。我没有意识到这是真的。然而,我没有一个安全值可用于
    COALESCE
    。我想要一个不需要假设给定值不会出现在数据集中的解决方案。请参阅下面我对@Gordon Linoff回答的评论:“但是,我没有一个安全值可用于COALESCE”。您可以将“1”替换为数据集中永远不会出现的内容(可以是“xxxxx”或“AAAA”或其他任何内容)
    SELECT * FROM (
    
    SELECT 'x' a, 'x' b FROM dual
        UNION ALL
    SELECT 'x' a, NULL b FROM dual
        UNION ALL
    SELECT NULL a, 'x' b FROM dual
        UNION ALL
    SELECT NULL a, NULL b FROM dual
        UNION ALL
    SELECT 'x' a, 'y' b FROM dual
        UNION ALL
    SELECT 'x' a, NULL b FROM dual
        UNION ALL
    SELECT NULL a, 'y' b FROM dual
        UNION ALL
    SELECT NULL a, NULL b FROM dual
    
    )
    
    WHERE NVL(a,'1')=NVL(b,'1')