J'ai des données séparées par des virgules dans une colonne:
Column
-------
a,b,c,d
Je veux diviser les données séparées par des virgules en plusieurs colonnes pour obtenir cette sortie:
Column1 Column2 Column3 Column4
------- ------- ------- -------
a b c d
Comment cela peut il etre accompli?
Si le nombre de champs dans le fichier CSV est constant, vous pouvez procéder comme suit:
select a[1], a[2], a[3], a[4]
from (
select regexp_split_to_array('a,b,c,d', ',')
) as dt(a)
Par exemple:
=> 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)
Si le nombre de champs dans le fichier CSV n'est pas constant, vous pouvez obtenir le nombre maximal de champs avec quelque chose comme ceci:
select max(array_length(regexp_split_to_array(csv, ','), 1))
from your_table
puis construisez la liste de colonnes a[1], a[2], ..., a[M]
appropriée pour votre requête. Donc, si ce qui précède vous donnait un maximum de 6, vous utiliseriez ceci:
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)
Vous pouvez combiner ces deux requêtes dans une fonction si vous le souhaitez.
Par exemple, donnez ces données (c'est un NULL dans la dernière ligne):
=> 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)
Puisque votre délimiteur est une simple chaîne fixe, vous pouvez également utiliser string_to_array
au lieu de regexp_split_to_array
:
select ...
from (
select string_to_array(csv, ',')
from csvs
) as dt(a);
Merci à Michael pour le rappel concernant cette fonction.
Vous devez vraiment repenser votre schéma de base de données pour éviter autant que possible la colonne CSV. Vous devriez plutôt utiliser une colonne de tableau ou une table séparée.
split_part()
fait ce que vous voulez en une étape:
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;
Ajoutez autant de lignes que vous avez d'éléments dans col
(maximum possible). Les colonnes dépassant les éléments de données seront des chaînes vides (''
).
Vous pouvez utiliser la fonction split.
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