首页 > 解决方案 > 在 SQL (Redshift) 中提取字符串并将列转换为行

问题描述

我在一个名为“食物”的表中有一个名为“描述”的列,其中包括多个用 分隔的食物名称,例如鸡肉、汤、面包、可乐

如何从列中提取每个项目并创建多行。例如,目前就像 {FoodID, FoodName, Description}==> {123, Meal, " chicken, soup, bread, coke "}

我需要的是

{FoodID, FoodName, Description}==> {123,膳食,鸡肉},{123,膳食,},{123,膳食,面包}等。

在 Redshift 中,我首先将“描述”列拆分为

select FoodID, FoodName, Description, 
SPLIT_PART(Description, ',',1) AS Item1, 
SPLIT_PART(Description, ',',1) AS Item2,
SPLIT_PART(Description, ',',1) AS Item3,.....till Item10
FROM Food

考虑到最多可以有 10 个项目,因此 Item10。将这些列 Item1 转换为 Item10 以存储为行的最佳方法是什么?我尝试了 UNION ALL,但考虑到大量数据需要更长的时间。

标签: sqlsplitmultiple-columnsamazon-redshiftrows

解决方案


您的问题在这里得到了专门针对 Redshift 的详细回答。您只需要将您的查询映射到那里提供的示例查询。您的查询将如下所示。

select  (row_number() over (order by true))::int as n into numbers from food limit 100;

这将创建数字表。

您的查询将变为:

select  foodId,   foodName,   split_part(Description,',',n) as descriptions from  food  cross join  numbers where  split_part(Description,',',n) is not null  and split_part(Description,',',n) != '';

现在,回到你最初关于性能的问题。

考虑到大量数据,这需要更长的时间。

考虑到 和 的典型数据仓库用例high readseldom write您应该保留stagging表中提到的典型食品数据,例如stg_food

您应该使用以下类型的查询来一次性插入实际food表,如下所示。

insert into  food  select  foodId,  foodName,  split_part(Description,',',n) as descriptions from  stg_food  cross join  numbers where   split_part(Description,',',n) is not null  and split_part(Description,',',n) != '';

这将写入一次并使您的选择查询更快。


推荐阅读