从数组中删除一个非唯一值

时间:2019-03-04 22:01:07

标签: sql arrays postgresql sql-update

给出PostgreSQL 9.6中的该表:

CREATE TABLE test_table (
   id int PRIMARY KEY
 , test_array text[]
);

带有这样的行:

INSERT INTO test_table (id, test_array)
VALUES (1 , '{A,A,A,B,B,B}');

如何删除一个单一的“ B”值?

我不能使用:

UPDATE test_table
SET test_array = array_remove(test_array, 'B')
WHERE id = 1;

,因为它删除了值'B'的 all 个元素。我只是想删除一个元素(例如第一个元素)。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

在扩展了此页面上提供的信息后,我找到了答案(由Sharon Ben Asher建议) https://dba.stackexchange.com/questions/94639/delete-array-element-by-index

创建此处提到的功能:

CREATE OR REPLACE FUNCTION f_array_remove_elem(anyarray, int)
RETURNS anyarray LANGUAGE sql IMMUTABLE AS
'SELECT $1[1:$2-1] || $1[$2+1:2147483647]';

并在此基础上实现array_position,该示例的最终声明:

UPDATE test_table SET test_array = f_array_remove_elem(test_array, array_position(test_array, 'B')) WHERE id = 1;

答案 1 :(得分:2)

基于我在dba.SE上找到的并有效利用的旧答案:

您可能会更进一步:

CREATE OR REPLACE FUNCTION f_array_remove_elem1(anyarray, anyelement)
  RETURNS anyarray LANGUAGE sql IMMUTABLE AS
'SELECT $1[:idx-1] || $1[idx+1:] FROM array_position($1, $2) idx';

此函数将要删除的元素的值作为第二个参数。相应地使用多态伪类型anyelement使其适用于任何数组类型。

然后UPDATE就是:

UPDATE test_table
SET    test_array = f_array_remove_elem1(test_array, 'B')
WHERE  id = 1;

db <>提琴here

尽管使用我的原始函数f_array_remove_elem()来获取索引位置而不是元素值,但是您可以不使用子查询:

UPDATE test_table
SET    test_array = f_array_remove_elem(test_array, array_position(test_array, 'B'))
WHERE  id = 1;

甚至可能比我的新功能快一点。
请注意,我的旧答案底部的较简单版本适用于Postgres 9.6。

答案 2 :(得分:0)

您可以尝试这个

select SUBSTRING ( '{A,A,A,B,B,B}',1,position('B' in '{A,A,A,B,B,B}') -1)||SUBSTRING ('{A,A,A,B,B,B}',position('B' in '{A,A,A,B,B,B}')+1)

首先找到B在字符串中的位置,然后获取子字符串,直到刚出现B之前,即'{A,A,A,然后获取离开B的其余字符串的子字符串,即,B,B }'