Если число полей в CSV постоянно, то вы можете сделать что-то вроде этого:
select a[1], a[2], a[3], a[4]
from (
select regexp_split_to_array('a,b,c,d', ',')
) as dt(a)
Например:
=> select a[1], a[2], a[3], a[4] from (select regexp_split_to_array('a,b,c,d', ',')) as dt(a);
a | a | a | a
---+---+---+---
a | b | c | d
(1 row)
Если количество полей в CSVне является константой, то вы можете получить максимальное количество полей с чем-то вроде этого:
select max(array_length(regexp_split_to_array(csv, ','), 1))
from your_table
и затем создать соответствующий список a[1], a[2], ..., a[M]
столбцов для вашего запроса.Таким образом, если из приведенного выше вы получите максимум 6, вы бы использовали это:
select a[1], a[2], a[3], a[4], a[5], a[6]
from (
select regexp_split_to_array(csv, ',')
from your_table
) as dt(a)
Вы можете объединить эти два запроса в функцию, если хотите.
Например, дать этоdata (в последней строке это NULL):
=> select * from csvs;
csv
-------------
1,2,3
1,2,3,4
1,2,3,4,5,6
(4 rows)
=> select max(array_length(regexp_split_to_array(csv, ','), 1)) from csvs;
max
-----
6
(1 row)
=> select a[1], a[2], a[3], a[4], a[5], a[6] from (select regexp_split_to_array(csv, ',') from csvs) as dt(a);
a | a | a | a | a | a
---+---+---+---+---+---
1 | 2 | 3 | | |
1 | 2 | 3 | 4 | |
1 | 2 | 3 | 4 | 5 | 6
| | | | |
(4 rows)
Поскольку ваш разделитель - простая фиксированная строка, вы также можете использовать string_to_array
вместо regexp_split_to_array
:
select ...
from (
select string_to_array(csv, ',')
from csvs
) as dt(a);
Спасибо Michael за напоминание об этой функции.
Вам действительно следует изменить схему базы данных, чтобы избежать столбца CSV, если это вообще возможно.Вместо этого вы должны использовать столбец массива или отдельную таблицу.