Ответ 1
Если количество полей в 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)
Вы могли бы объединить эти два запроса в функцию, если хотите.
Например, укажите эти данные (что 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, если это вообще возможно. Вместо этого вы должны использовать столбец массива или отдельную таблицу.