Skip to content
Advertisement

How to remove values from an array that exist in another array?

In PostgreSQL I have a table (Table) that contains an id column (ID) and another column (Values) that contains an array of strings. I have a select query (SelectQuery) that gets me an ID that matches Table.ID, as well as an array of values (RemoveValues). I would like to now remove from the Values array, any strings that are contained in the RemoveValues array that match on ID, updating Table.

Execute query that I can’t figure out

I can’t seem to figure out a good way to do this, I’ve played with a number of joins and the sql array methods and haven’t found anything that works. Is there’s a way to loop the remove() method for each element in RemoveValues? I’ve also tried something like this with no luck:

I’m feeling like my remaining option is a bash script, unless anyone can suggest a path forward using SQL?

Advertisement

Answer

There are many ways.

First, you have to define whether there can be duplicates or NULL values in either of the arrays – and how to deal with those if possible. And whether to preserve original order of elements.

Assuming either is possible, and these are the rules:

  • Count duplicates separately. So if Values has five elements ‘foo’ and RemoveValues has three elements ‘foo’, thee will be two element ‘foo’ in the result.

  • Treat NULL values equal. So NULL can be removed with NULL (though in other contexts NULL = NULL yields NULL).

  • Order of array elements does not have to be preserved.

  • <SelectQuery> produces unique ID values.

That matches the behavior of standard SQL EXCEPT ALL. See:

So:

About the LATERAL subquery:

Can be plain CROSS JOIN because an ARRAY constructor always produces a row.

You could wrap the functionality in a custom function:

Requires Postgres 14. See:

For older (or any) Postgres versions, and for any array type:

db<>fiddle here

(PARALLEL SAFE only for Postgres 9.6 or later, though.)

Then your query can be something like:

It’s unclear whether you actually locked in CaMeL-case spelling with double-quotes. I assumed as much, but better you don’t. See:

And your UPDATE can be:

The additional WHERE clause is optional to avoid empty updates. See:

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement