Разделить данные столбца через запятую на дополнительные столбцы - PullRequest
55 голосов
/ 21 декабря 2011

У меня есть данные, разделенные запятыми в столбце:

Column 
------- 
a,b,c,d 

Я хочу разделить данные, разделенные запятыми, на несколько столбцов, чтобы получить этот вывод:

Column1  Column2 Column3 Column4 
-------  ------- ------- -------
a        b       c       d 

Как это может бытьдостигли?

Ответы [ 3 ]

88 голосов
/ 23 декабря 2011

split_part() делает то, что вы хотите, за один шаг:

SELECT split_part(col, ',', 1) AS col1
     , split_part(col, ',', 2) AS col2
     , split_part(col, ',', 3) AS col3
     , split_part(col, ',', 4) AS col4
FROM   tbl;

Добавьте столько строк, сколько у вас есть элементов в col (возможныймаксимум).Столбцы, превышающие элементы данных, будут пустыми строками ('').

59 голосов
/ 21 декабря 2011

Если число полей в 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, если это вообще возможно.Вместо этого вы должны использовать столбец массива или отдельную таблицу.

1 голос
/ 09 января 2017

Вы можете использовать функцию разделения.

    SELECT 
    (select top 1 item from dbo.Split(FullName,',') where id=1 ) Column1,
    (select top 1 item from dbo.Split(FullName,',') where id=2 ) Column2,
    (select top 1 item from dbo.Split(FullName,',') where id=3 ) Column3,
    (select top 1 item from dbo.Split(FullName,',') where id=4 ) Column4,
    FROM MyTbl
...