81 votes

Diviser les données des colonnes séparées par des virgules en colonnes supplémentaires

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 ce résultat :

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

Comment y parvenir ?

128voto

Erwin Brandstetter Points 110228

split_part() fait ce que vous voulez en une seule é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 (le maximum possible).
Les colonnes dépassant les éléments de données seront des chaînes vides ( '' ).

10 votes

Et semble s'exécuter beaucoup plus rapidement que la version regexp_split_to_array.

1 votes

@JohnBarça : Toutes les fonctions d'expression régulière sont comparativement chères. Puissant, mais pour un prix ...

8 votes

Légende ! C'est de loin l'approche la plus rapide pour ce genre de problème.

89voto

mu is too short Points 205090

Si le nombre de champs dans le CSV est constant, vous pouvez faire quelque chose comme ceci :

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 CSV n'est pas constant, vous pouvez obtenir le nombre maximum de champs avec quelque chose comme ceci :

select max(array_length(regexp_split_to_array(csv, ','), 1))
from your_table

et ensuite construire les a[1], a[2], ..., a[M] pour votre requête. Donc, si la liste ci-dessus vous donne un maximum de 6, vous utiliserez 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 pourriez combiner ces deux requêtes en une seule fonction si vous le souhaitez.

Par exemple, donnez ces données (il y a 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 pourriez é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 de cette fonction.

Vous devriez vraiment revoir le schéma de votre base de données pour éviter la colonne CSV si possible. Vous devriez plutôt utiliser une colonne de type tableau ou une table séparée.

0 votes

Merci, je vais vérifier et revenir.

15 votes

Envisagez d'utiliser string_to_array au lieu de regexp_split_to_array il devrait être plus rapide puisqu'il n'a pas la surcharge du traitement des expressions régulières.

1 votes

@Michael Vous pouvez ajouter cela comme une autre réponse si vous le souhaitez. Ou je pourrais ajouter string_to_array comme une option dans le mien, je ne sais pas comment j'ai pu manquer ça.

0voto

vicky Points 27

Vous pouvez utiliser la fonction de fractionnement.

    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

1 votes

La question fait référence à PostgreSQL - c'est la syntaxe du serveur SQL ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X