HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

How to remove an element from a col with a CSV of ints in PostgreSQL 9.2?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
postgresqlwithcsvcolremoveelementhowfromints

Problem

I have PostgreSQL 9.2 database and a table:

id integer,
allowed_types character varying(255)`


Sample data as below:

id  allowed_types
1   3,4,5,13,14


How I can remove 4 and 5 from allowed_types which is a comma separated varchar list?

After removing, the result should be allowed_types = 3,13,14.

There are many records on that table, each allowed_types could contain different numbers, separated by comma.

I considered string_to_array() and array_remove(), but array_remove() is not in version 9.2, yet.

Solution

Proof of concept for regular expressions:

SELECT trim(regexp_replace(',' || '3,4,5,13,14' || ',', ',(4|5)(?=,)', '', 'g'), ',');


Returns:

3,13,14


Pad commas to cover corner cases at begin and end. The regular expression ',(4|5)(?=,)' explained:

, ... literal comma

(4|5) ... two branches: either 4 or 5

(?=,) ... positive lookahead: next character is a literal comma

Would need a functional trigram index on (',' || allowed_types || ',') for good performance with big tables (only slightly bigger than a regular index due to the added commas). Details:

  • How is LIKE implemented?



Or, with a more sophisticated regular expression, you can work with the original column and a trigram index on just (allowed_types):

SELECT ltrim(regexp_replace('3,4,5,13,14', '((,|^)(4|5))(?=,|$)', '', 'g'), ',');


dbfiddle here

But I expect the first solution to be faster: complex regular expressions are more expensive.
The according UPDATE

UPDATE tbl
SET    allowed_types = trim(regexp_replace(',' || allowed_types || ',', ',(4|5)(?=,)', '', 'g'), ',')
WHERE  ',' || allowed_types || ',' ~ ',(4|5),';  -- here, plain comma is good


What I would really do:

Update to a current version of Postgres (pg 9.2 reaches EOL Sept 2017) and probably use a normalized 1:n design.

Code Snippets

SELECT trim(regexp_replace(',' || '3,4,5,13,14' || ',', ',(4|5)(?=,)', '', 'g'), ',');
SELECT ltrim(regexp_replace('3,4,5,13,14', '((,|^)(4|5))(?=,|$)', '', 'g'), ',');
UPDATE tbl
SET    allowed_types = trim(regexp_replace(',' || allowed_types || ',', ',(4|5)(?=,)', '', 'g'), ',')
WHERE  ',' || allowed_types || ',' ~ ',(4|5),';  -- here, plain comma is good

Context

StackExchange Database Administrators Q#177962, answer score: 6

Revisions (0)

No revisions yet.