Разделить значения по нескольким строкам в RedShift

Вопрос о том, как разбить поле (например, строку CSV) на несколько строк, уже ответил: Разделить значения по нескольким строкам .

Однако этот вопрос относится к MSSQL, и ответы используют различные функции, для которых нет эквивалентов RedShift.

Для полноты, вот пример того, что я хотел бы сделать:

Текущие данные:

| Key | Data | +-----+----------+ | 1 | 18,20,22 | | 2 | 17,19 | 

Необходимые данные:

 | Key | Data | +-----+----------+ | 1 | 18 | | 1 | 20 | | 1 | 22 | | 2 | 17 | | 2 | 19 | 

Теперь я могу предложить walkaround для случая небольшого ограниченного числа элементов в поле CSV: используйте split_part и объединение во всех возможных расположениях массива, например:

 SELECT Key, split_part(Data, ',', 1) FROM mytable WHERE split_part(Data, ',', 1) != "" UNION SELECT Key, split_part(Data, ',', 2) FROM mytable WHERE split_part(Data, ',', 2) != "" -- etc. etc. 

Однако это явно неэффективно и не будет работать для более длинных списков.

Любые лучшие идеи о том, как это сделать?

РЕДАКТИРОВАТЬ:

Существует также несколько аналогичный вопрос о умножении строк: разбиение строк в Redshift . Однако я не вижу, как этот подход может быть применен здесь.

EDIT 2:

Возможный дубликат: красное смещение. Преобразуйте значения, разделенные запятыми, в строки . Но ничего нового – ответ @Masashi Miyazaki похож на мое предложение выше и страдает от одних и тех же вопросов.

Вот ответ Redshift, он будет работать с 10 тысячами значений в строке.

Настройка тестовых данных

 create table test_data (key varchar(50),data varchar(max)); insert into test_data values (1,'18,20,22'), (2,'17,19') ; 

код

 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(data, '\\,') + 1) FROM test_data) ) , expanded_input AS ( SELECT key, split_part(data, ',', s.gen_num) AS data FROM test_data AS td JOIN splitter AS s ON 1 = 1 WHERE split_part(data, ',', s.gen_num) <> '' ) SELECT * FROM expanded_input order by key,data; 

Вы можете использовать экземпляр RDS PostgreSql и создать dblink для RedShift. Затем вы можете манипулировать по набору результатов, как в обычной базе данных PostgreSQL, и даже вернуть результат обратно в RedShift через тот же самый dblink.