我有一个包含 4 个数组列的表。结果如下:
ids signed_ids new_ids new_ids_signed
{1,2,3} | {2,1,3} | {4,5,6} | {6,5,4}
无论如何,通过忽略元素的顺序来比较它们ids
以signed_ids
使它们相等?
我有一个包含 4 个数组列的表。结果如下:
ids signed_ids new_ids new_ids_signed
{1,2,3} | {2,1,3} | {4,5,6} | {6,5,4}
无论如何,通过忽略元素的顺序来比较它们ids
以signed_ids
使它们相等?
您可以使用包含的运算符:
(array1 <@ array2 and array1 @> array2)
附加模块intarray为 的数组integer
提供运算符,这些运算符通常(快得多)。每个数据库安装一次(在 Postgres 9.1 或更高版本中):
CREATE EXTENSION intarray;
那么你就可以:
SELECT uniq(sort(ids)) = uniq(sort(signed_ids));
或者:
SELECT ids @> signed_ids AND ids <@ signed_ids;
大胆强调来自 intarray 的函数和运算符。
在第二个示例中,如果 left 和 right 参数是 type ,则运算符解析到达专门的 intarray 运算符integer[]
。
这两个表达式都将忽略元素的顺序和重复性。在此处的有用手册中进一步阅读。
intarray
运算符仅适用于integer
( int4
) 的数组,而不适用于bigint
( int8
) 或smallint
( int2
) 或任何其他数据类型。
与默认的泛型运算符不同,intarray
运算符不接受数组中的 NULL 值。任何涉及的数组中的 NULL 都会引发异常。如果您需要使用 NULL 值,您可以默认使用标准的通用运算OPERATOR
符,方法是使用构造对运算符进行模式限定:
SELECT ARRAY[1,4,null,3]::int[] OPERATOR(pg_catalog.@>) ARRAY[3,1]::int[]
通用运算符不能将索引与intarray
运算符类一起使用,反之亦然。
有关的:
最简单的做法是对它们进行排序并比较它们的排序。请参阅PostgreSQL 中的排序数组。
给定样本数据:
CREATE TABLE aa(ids integer[], signed_ids integer[]);
INSERT INTO aa(ids, signed_ids) VALUES (ARRAY[1,2,3], ARRAY[2,1,3]);
最好的办法是,如果数组条目始终是整数,则使用 intarray 扩展名,正如Erwin 在他的回答中解释的那样。它比任何纯 SQL 公式都要快得多。
否则,对于适用于任何数据类型的通用版本,请定义array_sort(anyarray)
:
CREATE OR REPLACE FUNCTION array_sort(anyarray) RETURNS anyarray AS $$
SELECT array_agg(x order by x) FROM unnest($1) x;
$$ LANGUAGE 'SQL';
并使用它对排序后的数组进行排序和比较:
SELECT array_sort(ids) = array_sort(signed_ids) FROM aa;
有一个重要的警告:
SELECT array_sort( ARRAY[1,2,2,4,4] ) = array_sort( ARRAY[1,2,4] );
将是错误的。这可能是也可能不是您想要的,取决于您的意图。
或者,定义一个函数array_compare_as_set
:
CREATE OR REPLACE FUNCTION array_compare_as_set(anyarray,anyarray) RETURNS boolean AS $$
SELECT CASE
WHEN array_dims($1) <> array_dims($2) THEN
'f'
WHEN array_length($1,1) <> array_length($2,1) THEN
'f'
ELSE
NOT EXISTS (
SELECT 1
FROM unnest($1) a
FULL JOIN unnest($2) b ON (a=b)
WHERE a IS NULL or b IS NULL
)
END
$$ LANGUAGE 'SQL' IMMUTABLE;
进而:
SELECT array_compare_as_set(ids, signed_ids) FROM aa;
array_sort
这与比较两个ed 值略有不同。array_compare_as_set
将消除重复,使array_compare_as_set(ARRAY[1,2,3,3],ARRAY[1,2,3])
真实,而array_sort(ARRAY[1,2,3,3]) = array_sort(ARRAY[1,2,3])
将是错误的。
这两种方法的性能都会很差。考虑确保您始终首先存储已排序的数组。
如果您的数组没有重复并且具有相同的维度:
@>
array_length
长度必须与两边的尺寸相匹配select (string_agg(a,',' order by a) = string_agg(b,',' order by b)) from (select unnest(array[1,2,3,2])::text as a,unnest(数组[2,2,3,1])::text as b) A