Sql 红移将新表中的单个动态列拆分为多行

Sql 红移将新表中的单个动态列拆分为多行,sql,amazon-redshift,Sql,Amazon Redshift,有一张像这样的桌子: uid | segmentids -------------------------+---------------------------------------- f9b6d54b-c646-4bbb-b0ec | 4454918|4455158|4455638|4455878|4455998 asd7a0s9-c646-asd7-b0ec | 1265899|1265923|1265935|12668

有一张像这样的桌子:

       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
如何使用以下内容创建新表:

      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
段的数量是动态的,可以随每条记录的不同而变化。 我尝试了带分隔符的Split函数,但它需要字符串索引,这在这里是动态的


有什么建议吗?

这是红移的答案,每行最多可使用10000个段ID值

测试数据

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')
;
代码

前两个cte步骤ten_编号和生成的_编号用于生成大量行,这是必需的,因为不支持生成_系列

下一步拆分器只获取等于最大分隔符数+1(即最大段数)的行数


最后,我们将splitter与输入数据交叉连接,使用split_part获取相关值,然后排除空白部分,这些空白部分是由于行的段数<最大段数

您标记了多个dbms产品而导致的,为什么?这里的动态是什么?您在示例中使用的是index=1-显示一些不同的示例来解释请理解问题-请将您的标签更改为您正在使用的标签,因为答案完全不同!工作得很有魅力。还在想办法。我得到了索引部分,但是您如何将其与原始表中的UID进行匹配?为什么我们在十个数字中使用1000、100和10这样的值?它将生成10000行输出。每行的gen_num递增。通常,您可以使用generate_series函数进行此操作,但这在红移中是不可能的,因此这是一个聪明的解决方法。如果你不需要10000,那么你可以删除该部分。不过,这样做几乎没有开销。匹配是作为一个交叉连接从test_split as ts join splitter as s ON 1=1完成的。每个测试_分割都与每个分割行合并。我们只有从1到文件中任何地方的最大段数的拆分行。然而,它很漂亮-在我的时代,我来学习立即可读代码的价值。正确的解决方案是在管道中包括一个阶段,该阶段在spark或类似软件中进行功能转换。然后,在通过SelectSplitColSegmentId、|.aliasseg_数组将分隔列转换为任何数组后,这个困难的逻辑变成df.WithColumnSecgment_id、functions.explodeseg_数组
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;