根据列值将一行拆分为多行

Posted

技术标签:

【中文标题】根据列值将一行拆分为多行【英文标题】:Split a row into multiple rows based on a column value 【发布时间】:2019-04-25 17:20:17 【问题描述】:

我正在尝试根据列值将表中的记录拆分为 2 条记录。输入表显示 3 种类型的产品及其价格。对于特定的产品(行),只有其对应的列才有价值。其他列有 Null。

我的要求是 - 每当产品列值(在一行中)是复合的(即有多个产品,例如 Bolt + Brush)时,记录必须分成两行 - 对于复合产品类型,每行 1 行.

因此,在此示例中,请注意第二行(在输入中)如何分成 2 行 -> 1 行用于“Bolt”,另一行用于“Brush”,它们的价格从相应的列中提取(即在这种情况下,“螺栓”= 3.99 美元,“刷子”= 6.99 美元)

注意:对于复合产品值,最多可以有 2 个产品,如本例所示(例如螺栓 + 刷子)

CustId | Product        | Hammer | Bolt  | Brush
--------------------------------
12345  | Hammer         | $5.99  | Null  | Null  
53762  | **Bolt+Brush** | Null   | $3.99 | $4.99  
43883  | Brush          | Null   | Null  | $4.99  

我尝试使用 CTE 通过 UNION ALL 创建 2 条预定记录,然后使用 CTE 创建 main_table Left Outer Join,以便连接产生 2 条记录。

#CustId   | Product   | Price  #
12345     | Hammer    | $5.99  
**53762** | **Bolt**  | $3.99  
**53762** | **Brush** | $4.99  
43883     | Brush     | $4.99  

这只能通过 Spark-SQL 解决。

【问题讨论】:

如果相关产品在 Product 列中,那么各种 Price 列是否只有一个非空值?如果是这样,您也许可以设计一个 3 阶段的 UNION 语句;一个阶段 HAMMER 不为空,一个阶段 BOLT 不为空,一个阶段 BRUSH 不为空。 【参考方案1】:

我认为这会奏效:

select CustId, 'Hammer' as product, Hammer
from t
where Product like '%Hammer%'
union all
select CustId, 'Bolt' as product, Bolt
from t
where Product like '%Bolt%'
union all
select CustId, 'Brush' as product, Brush
from t
where Product like '%Brush%';

【讨论】:

【参考方案2】:

这也可以

select custid, product, 
            case when product like '%Hammer%' then hammer 
                 when product like '%Bolt%'   then bolt 
            else brush end as Price from
(select custid, explode(split(product,'\\+')) as product,  hammer, bolt, brush  
from t) x;

【讨论】:

完美运行

以上是关于根据列值将一行拆分为多行的主要内容,如果未能解决你的问题,请参考以下文章

通过解析列中的字符串值将表中的一行拆分为多行

使用 ETL 工具按列值将数据拆分为不定数量的表

按列值将数据框拆分为两个[重复]

sql如何把行拆分为几行

如何根据另一列值将一列分成多个?

sql一行拆分多行记录