2017-10-17 8 views
0

Avec une table comme:Redshift diviser une colonne dynamique unique en plusieurs lignes dans nouvelle table

 uid    |   segmentids 
-------------------------+---------------------------------------- 
f9b6d54b-c646-4bbb-b0ec | 4454918|4455158|4455638|4455878|4455998 
asd7a0s9-c646-asd7-b0ec | 1265899|1265923|1265935|1266826|1266596 
gd3355ff-cjr8-assa-fke0 | 2237557|2237581|2237593 
laksnfo3-kgi5-fke0-b0ec | 4454918|4455158|4455638|4455878 

Comment créer une nouvelle table avec:

 uid    |   segmentids 
-------------------------+--------------------------- 
f9b6d54b-c646-4bbb-b0ec |   4454918 
f9b6d54b-c646-4bbb-b0ec |   1265899 
f9b6d54b-c646-4bbb-b0ec |   2237557 
f9b6d54b-c646-4bbb-b0ec |   4454918 
f9b6d54b-c646-4bbb-b0ec |   4454918 
asd7a0s9-c646-asd7-b0ec |   1265899 
asd7a0s9-c646-asd7-b0ec |   1265923 
asd7a0s9-c646-asd7-b0ec |   1265935 
asd7a0s9-c646-asd7-b0ec |   1266826 
asd7a0s9-c646-asd7-b0ec |   1266596 

Le nombre de segments sont dynamiques, peuvent varier avec chaque enregistrement. J'ai essayé la fonction Split avec délimiteur, mais elle nécessite l'index dans la chaîne, qui est dynamique ici.

Des suggestions?

+0

tag Vous plusieurs produits DBMS, comment venir? – jarlh

+0

qu'est-ce qui est dynamique ici? vous utilisez index = 1 dans votre exemple - montrez un échantillon différent pour expliquer s'il vous plaît –

+0

je comprends la question - s'il vous plaît changer vos tags pour être juste celui que vous utilisez comme la réponse est complètement différente! –

Répondre

4

Voici la réponse Redshift, il fonctionnera avec jusqu'à 10 000 valeurs d'identifiants de segment par ligne.

données de test

create table test_split (uid varchar(50),segmentids varchar(max)); 
insert into test_split 
    values 
     ('f9b6d54b-c646-4bbb-b0ec','4454918|4455158|4455638|4455878|4455998'), 
     ('asd7a0s9-c646-asd7-b0ec','1265899|1265923|1265935|1266826|1266596'), 
     ('asd7345s9-c646-asd7-b0ec','1235935|1263456|1265675696'), 
     ('as345a0s9-c646-asd7-b0ec','12765899|12658883|12777935|144466826|1266226|12345') 
; 

Code

with ten_numbers as (select 1 as num union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) 
    , generted_numbers AS 
(
    SELECT (1000 * t1.num) + (100 * t2.num) + (10 * t3.num) + t4.num AS gen_num 
    FROM ten_numbers AS t1 
     JOIN ten_numbers AS t2 ON 1 = 1 
     JOIN ten_numbers AS t3 ON 1 = 1 
     JOIN ten_numbers AS t4 ON 1 = 1 
) 
    , splitter AS 
(
    SELECT * 
    FROM generted_numbers 
    WHERE gen_num BETWEEN 1 AND (SELECT max(REGEXP_COUNT(segmentids, '\\|') + 1) 
           FROM test_split) 
) 
    --select * from splitter; 
    , expanded_input AS 
(
    SELECT 
     uid, 
     split_part(segmentids, '|', s.gen_num) AS segment 
    FROM test_split AS ts 
     JOIN splitter AS s ON 1 = 1 
    WHERE split_part(segmentids, '|', s.gen_num) <> '' 
) 
SELECT * FROM expanded_input; 

les 2 premières étapes de l'ECU (ten_numbers et generated_numbers) sont utilisés pour générer un nombre de lignes, ceci est nécessaire parce que generate_series ne sont pas pris en charge

L'étape suivante (séparateur) prend juste un nombre de lignes égal au nombre maximum de délimiteurs + 1 (qui est le nombre maximum de segments)

enfin, nous d'une jointure croisée splitter avec les données d'entrée, prenez la valeur liée à l'aide SPLIT_PART et exclure des parties vides (qui sont causées lorsque la ligne a < le nombre maximum de segments)

+0

Travailler comme un charme. J'essaie toujours de comprendre comment. Je reçois la partie indexation, mais comment l'associez-vous aux uids comme dans le tableau d'origine? –

+0

Et pourquoi utilisons-nous des valeurs comme 1000, 100 et 10 dans ten_numbers? –

+0

il génère 10000 lignes de sortie. avec gen_num incrémentant pour chaque ligne. normalement, vous pouvez utiliser la fonction generate_series pour cela, mais cela n'est pas possible dans redshift, donc c'est une solution astucieuse. Si vous n'avez pas besoin de 10000 alors vous pouvez supprimer cette partie. il n'y a pratiquement aucun frais généraux en faisant cela cependant. –