Skip to content
Advertisement

Split comma separated values into target table with fixed number of columns

I have a table with a single column in a Postgres 13.1 database. It consists of many rows with comma-separated values – around 20 elements at most.

I want to split the data into multiple columns. But I have only a limited number of columns say 5 and more than 5 CSV values in a single row, so excess values must be shifted to new/next row). How to do this?

Example:

Columns are only 5, so the output would be like:

Advertisement

Answer

It is typically bad design to store CSV values in a single column. If at all possible, use an array or a properly normalized design instead.

While stuck with your current situation …

For known small maximum number of elements

A simple solution without trickery or recursion will do:

db<>fiddle here

id being the PK of the original table.
This assumes ‘, ‘ as separator, obviously.
You can adapt easily.

Related:

For unknown number of elements

Various ways. One way use regexp_replace() to replace every fifth separator before unnesting …

db<>fiddle here

This assumes that the chosen separator ; never appears in your strings. (Just like , can never appear.)

The regular expression pattern is the key: '((?:.*?,){4}.*?),'

(?:)“non-capturing” set of parentheses
()“capturing” set of parentheses
*?non-greedy quantifier
{4}? … sequence of exactly 4 matches

The replacement '1;' contains the back-reference 1.

'g' as fourth function parameter is required for repeated replacement.

Further reading:

Other ways to solve this include a recursive CTE or a set-returning function …

Fill from right to left

(Like you added in How to put values starting from the right side into columns?)
Simply count down numbers like:

db<>fiddle here

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