是一种 postgres 组合方式IS DISTINCT FROM
还是ANY
其他一些巧妙的方式来获得相同的结果?
select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo <> any(array[null, 'A']);
count
-------
1
(1 row)
select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo is distinct from any(array[null, 'A']);
ERROR: syntax error at or near "any"
LINE 3: where foo is distinct from any(array[null, 'A']);
^
将其视为语法问题,
ANY
定义为(在Row and Array Comparisons中):但
is distinct from
它不是运算符,它是一个“构造”,正如我们在比较运算符中所说的那样:由于 PostgreSQL 有用户定义的运算符,我们可以为此目的定义一个运算符/函数组合:
然后它可以先于
ANY
:操作员
这是建立在@Daniel 聪明的 operator之上的。
在此过程中,使用多态类型创建函数/运算符组合。然后它适用于任何类型 - 就像构造一样。
并制作函数
IMMUTABLE
。使用 symbolhound 进行的快速搜索是空的,因此该运算符
<!>
似乎没有在任何模块中使用。如果您打算大量使用此运算符,您可能会进一步充实它以帮助查询规划器(如评论中建议的 losthorse)。对于初学者,您可以添加
COMMUTATOR
andNEGATOR
子句来辅助查询优化器。CREATE OPERATOR
从上面替换为:并添加:
但是附加子句对手头的用例没有帮助,并且仍然不会使用普通索引。实现这一点要复杂得多。(我没试过。)详情请阅读手册中的“运营商优化信息”一章。
测试用例
只有当数组中的所有值都相同时,问题中的测试用例才能成功。对于问题 (
'{null,A}'::text[]
) 中的数组,结果始终为 TRUE。这是故意的吗?我为“IS DISTINCT FROM ALL”添加了另一个测试:标准运算符的替代方案
几乎可以翻译成
foo = ALL (test_arr)
产量...TRUE
.. 如果所有元素都是foo
FALSE
.. 如果任何NOT NULL
元素是<> foo
NULL
.. 如果至少一个元素IS NULL
并且没有元素是<> foo
所以,剩下的极端情况是
-
foo IS NULL
- 并且
test_arr
只包含NULL
元素。如果可以排除其中任何一个,我们就完成了。因此,使用简单的测试 if
- 列已定义
NOT NULL
。-或者你知道数组永远不会都是 NULL。
否则,额外测试:
Where
'A'
和'B'
可以是任何不同的值。在这个相关问题下的解释和替代方案:Is array all NULLs in PostgreSQL
同样,如果您知道任何不能存在于 中的值,
test_arr
例如空字符串''
,您仍然可以简化:这是检查所有组合的完整测试矩阵:
这比Andriy 的
EXCEPT
解决方案要冗长一些,但速度要快得多。也许像这样:
请注意,不仅
null
在“数组”中,而且在null
以z
这种方式比较。