如何使用SQL UNPIVOT实现列转行 生成品牌维度扁平化销量表
SQL宽表转品牌销量明细表实现方案
以下方案默认原宽表表名为 brand_sales_wide,原表中子品牌列名分别为 JPGL FF、JPGL Switch、LS Berry、LS Lemon、Star FF、Star Next,主品牌汇总列名为 JPGL、LS、Star。如果实际表名、列名有差异,直接替换SQL中对应的标识符即可。
支持原生UNPIVOT方言的实现(SQL Server/Oracle/PostgreSQL 11+等)
核心逻辑是先通过UNPIVOT把所有品牌列转为行,再通过预定义的品牌归属映射过滤主品牌汇总行,同时匹配对应主品牌:
SELECT Customer, Brand, Sub_Brand AS `Sub-Brand`, Qty FROM ( SELECT * FROM brand_sales_wide UNPIVOT ( Qty FOR Sub_Brand IN ( [JPGL FF], [JPGL Switch], [JPGL], [LS Berry], [LS Lemon], [LS], [Star FF], [Star Next], [Star] ) ) AS unpivoted_result ) t INNER JOIN ( -- 主品牌-子品牌映射表,仅保留需要输出的子品牌 SELECT 'JPGL' AS Brand, 'JPGL FF' AS Sub_Brand UNION ALL SELECT 'JPGL', 'JPGL Switch' UNION ALL SELECT 'LS', 'LS Berry' UNION ALL SELECT 'LS', 'LS Lemon' UNION ALL SELECT 'Star', 'Star FF' UNION ALL SELECT 'Star', 'Star Next' ) AS brand_mapping ON t.Sub_Brand = brand_mapping.Sub_Brand;
注:上面SQL中列名用
[]包裹是SQL Server的标识符写法,Oracle请替换为双引号"",MySQL请替换为反引号`。
全兼容UNION ALL实现(适配所有SQL数据库,含低版本MySQL)
如果使用的数据库不支持原生UNPIVOT语法,可以直接通过UNION ALL逐个子品牌查询拼接结果,天然过滤主品牌汇总行,不需要额外关联映射:
SELECT Customer, 'JPGL' AS Brand, 'JPGL FF' AS `Sub-Brand`, `JPGL FF` AS Qty FROM brand_sales_wide UNION ALL SELECT Customer, 'JPGL', 'JPGL Switch', `JPGL Switch` FROM brand_sales_wide UNION ALL SELECT Customer, 'LS', 'LS Berry', `LS Berry` FROM brand_sales_wide UNION ALL SELECT Customer, 'LS', 'LS Lemon', `LS Lemon` FROM brand_sales_wide UNION ALL SELECT Customer, 'Star', 'Star FF', `Star FF` FROM brand_sales_wide UNION ALL SELECT Customer, 'Star', 'Star Next', `Star Next` FROM brand_sales_wide;
输出结果说明
两种写法最终输出结构完全一致,包含Customer、Brand、Sub-Brand、Qty四个字段,每个客户对应6条子品牌的销量明细,无主品牌汇总行,符合目标表要求。以客户100、200的测试数据为例,输出结果结构如下:
| Customer | Brand | Sub-Brand | Qty |
|---|---|---|---|
| 100 | JPGL | JPGL FF | 表中对应存储值 |
| 100 | JPGL | JPGL Switch | 表中对应存储值 |
| 100 | LS | LS Berry | 表中对应存储值 |
| 100 | LS | LS Lemon | 表中对应存储值 |
| 100 | Star | Star FF | 表中对应存储值 |
| 100 | Star | Star Next | 表中对应存储值 |
| 200 | JPGL | JPGL FF | 表中对应存储值 |
| 200 | JPGL | JPGL Switch | 表中对应存储值 |
| 200 | LS | LS Berry | 表中对应存储值 |
| 200 | LS | LS Lemon | 表中对应存储值 |
| 200 | Star | Star FF | 表中对应存储值 |
| 200 | Star | Star Next | 表中对应存储值 |
内容的提问来源于stack exchange,提问作者Nesma Huda
相关产品推荐
相关产品推荐

