我试图弄清楚最简单的通用 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
条款,即使其更紧凑,同时保持逻辑正确吗?
P.S。:我无法对任何SQL纯粹主义者坚持认为" NULL
不是一个值"。对于我的实用目的,如果a
包含NULL
且b
没有,则a
与{{不同 1}}。它不是"未知"他们是否不同所以,请提前告知那条小巷没有争论!
P.P.S。:我的SQL风格是Oracle 11g。
P.P.P.S。:有人认为这个问题与" Is there better Oracle operator to do null-safe equality check?"但粗略检查一下这个问题将会显示答案没有比这个帖子上发布的答案更有帮助,并且不满足我特定的,明确规定的标准。仅仅因为它们相似并不能使它们重复。我永远不明白为什么SO上的人如此努力地迫使我的问题X成为别人的问题Y.
答案 0 :(得分:2)
您可以将其简化为:
WHERE (a IS NULL AND b IS NULL) OR
(a = b)
不需要IS NOT NULL
。
如果您有一个“安全”值(即从未使用过的值),您可以这样做:
WHERE COALESCE(a, ' ') = COALESCE(b, ' ')
这假定' '
不是有效值。
答案 1 :(得分:1)
我发现Ask Tom文章"Safely Comparing NULL Columns As Equal"最有帮助。在Oracle中,您可以使用DECODE
函数执行此操作:
WHERE 1 = DECODE(a, b, 1, 0)
这是迄今为止我见过的最紧凑的解决方案。
答案 2 :(得分:0)
简单不一定是高效的。
考虑这种可能性。
WHERE X || 'x' = Y || 'x'
如果您想真正推动信封,请使用 SYS_OP_MAP_NONNULL
答案 3 :(得分:-1)
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')