postgres - 比较两个数组

时间:2009-10-30 00:32:44

标签: sql arrays postgresql

postgres有一个数组数据类型,在本例中是一个数字数组:

CREATE TABLE sal_emp (name text, pay_by_quarter integer[]);
INSERT INTO sal_emp VALUES ('one', '{1,2,3}');
INSERT INTO sal_emp VALUES ('two', '{4,5,6}');
INSERT INTO sal_emp VALUES ('three', '{2,4,6}');
SELECT * FROM sal_emp;

Result:
one, {1,2,3}
two, {4,5,6}
three, {2,4,6}

据我所知,您只能按如下方式查询数组:

SELECT * FROM sal_emp WHERE 4=ANY(pay_by_quarter);
SELECT * FROM sal_emp WHERE ARRAY[4,5,6]=pay_by_quarter;

这意味着您可以选择一个数组包含单个参数匹配的行,或者整个数组是否与数组参数匹配。

我需要选择一行,其中行的数组的任何成员都匹配参数数组的任何成员 - 有点像'IN',但我无法弄清楚如何。我尝试过以下两种方法,但都不起作用:

SELECT * from sal_emp WHERE ARRAY[4,5,6]=ANY(pay_by_quarter);
SELECT * from sal_emp WHERE ANY(pay_by_quarter) IN (4,5,6);

我认为我可以将数组转换为字符串,但这听起来很糟糕......

任何想法?

4 个答案:

答案 0 :(得分:24)

想通了......有一个&&操作

http://www.postgresql.org/docs/8.2/static/functions-array.html

“&&重叠(共有元素)ARRAY [1,4,3]&& ARRAY [2,1]”

答案 1 :(得分:3)

为了在 Postgress 中比较数组,有数组运算符。
在此处找到运算符部分:https://www.postgresql.org/docs/current/functions-array.html

比较两个数组的一种快速方法是这样做,

( (ARRAY_1 @> ARRAY_2) AND (ARRAY_1 <@ ARRAY_2) )

基本上检查 ARRAY_2 中的所有唯一值是否都存在于 ARRAY_1 AND 中,反之亦然。 不要忘记结合使用检查/条件/比较(AND)

这些称为包含运算符,用于检查一个数组中的所有唯一值并将其与另一个进行比较。它们也被称为鸟类运算符,因为运算符 @> AND <@ 类似于鸟的头部。

它的工作方式如下:

ARRAY_1 <@ ARRAY_2
// Check/Direction: Left-to-Right
// Checks if all the unique elements in ARRAY_1 is present in ARRAY_2 as well. If yes, it will return TRUE
// Please note this will return TRUE even if ARRAY_2 has extra elements that are not present in ARRAY_1

同样,

ARRAY_1 @> ARRAY_2
// Note we have changed the operator to '@>' from '<@'. Check/Direction: Right-to-Left
// Checks if all the unique elements in ARRAY_2 is present in ARRAY_1 as well. If yes, it will return TRUE
// Please note this will return TRUE even if ARRAY_1 has extra elements that are not present in ARRAY_2

所以即使元素的顺序不同,它仍然有效。

查看 > OR < 符号的一个简单方法是不要混淆并记住这一点。
将小于号指向的数组(唯一元素)与大于号指向的数组(唯一元素)进行比较。
因此,指向大于号的 ARRAY 可以包含额外的唯一元素,并且仍然返回 TRUE

让我们尝试一些例子

SELECT array[1, 2, 3] @> array[1, 2, 3] AS RESULT
!-- Returns TRUE (Check is Right-to-Left)

SELECT array[1, 2, 3] @> array[3, 1, 2] AS RESULT
!-- Returns TRUE (Check is Right-to-Left)

SELECT array[1, 2, 3, 3, 3, 3] @> array[1, 2, 3] AS RESULT
!-- Returns TRUE (Check is Right-to-Left)

SELECT array[1, 2, 3, 3, 3, 3] <@ array[3, 2, 1, 3, 2, 5] AS RESULT
!-- Returns TRUE (Check is Left-to-Right)

SELECT array[1, 2, 3, 4] <@ array[1, 2, 3] AS RESULT
!-- Returns FALSE (Check is Left-to-Right)

SELECT array[1, 2, 3, 4] @> array[1, 2, 3] AS RESULT
!-- Returns TRUE (Check is Right-to-Left)

SELECT array[1, 2, 3] <@ null AS RESULT
!-- Returns empty (Check is Left-to-Right)

SELECT array[1, 2, 3] @> null AS RESULT
!-- Returns empty (Check is Right-to-Left)

SELECT null <@ null AS RESULT
!-- Doesn't work if both the values are null - Error: Operator is not unique: unknown <@ unknown

SELECT array[1, 2, 3] <@ array[] AS RESULT
!-- Doesn't work on empty arrays - Error: Cannot determine type of empty array

SELECT array[] <@ array[] AS RESULT
!-- Doesn't work on empty arrays - Error: Cannot determine type of empty array

请注意

  • 这用于比较数组。
  • 从两个数组中提取唯一值 - 然后比较它们。
  • 它不会检查 ARRAY 中元素的数量。即即使两个数组的长度不同,它也可以返回 TRUE([1, 2] @> [1] OR [1, 1] @> [1] 仍然是 TRUE
  • 如果两个值都为 NULL
  • 则不起作用
  • 如果数组中的任何一个为空 ([]) 则不起作用

答案 2 :(得分:0)

不试图not毁pstanton的答案,而是澄清用例。

要具有两个(或更多)具有任意值列表的列的 any 满足的条件:

 select * from mytable
 where array(col1, col2) && array('foo', 'bar', baz')

答案 3 :(得分:0)

将一个数组的两个元素与另一个数组的元素进行至少一个匹配我们可以使用 && 运算符进行比较。仅当每个数组中至少有一个元素匹配时,它才会返回 true。

虽然这个问题的正确答案已经存在了几十年,但为了让初学者更清楚,我还是添加了这个例子。

架构:

 create table mytable (id int, value text[]);
 insert into mytable values (1,'{"dog", "cat", "fish"}');
 insert into mytable values (2,'{"elephant", "mouse"}');
 insert into mytable values (3,'{"lizard", "dog", "parrot"}');
 insert into mytable values (4,'{"bear", "bird", "cat"}');

查询:

 select * from mytable where array['dog', 'cat']&&(value);

输出:

<头>
id 价值
1 {狗、猫、鱼}
3 {蜥蜴,狗,鹦鹉}
4 {熊、鸟、猫}

db<>fiddle here

Query#2(使用通配符匹配数组元素)

要使用通配符比较数组元素,您可以使用 unnest() 解析两个数组的每个元素并使用 Like 运算符比较它们。

   SELECT    distinct m.*
   FROM  mytable m, unnest(value)b 
   inner join  unnest(array['dog%', 'ca%']) a 
   on b LIKE a 

输出:

<头>
id value
1 {dog,cat,fish}
3 {lizard,dog,parrot}
4 {bear,bird,cat}

db<>fiddle here