使用 SQL 将数据从行转换为列
Posted
技术标签:
【中文标题】使用 SQL 将数据从行转换为列【英文标题】:Transform data from rows to columns using SQL 【发布时间】:2020-10-15 10:02:22 【问题描述】:数据结构说明
假设我们有一个订单项目表(即一行代表一个订单项目)。每个订单项都有product_type
(“A”或“B”)、amount
和currency
。
一份订单 (order_id
) 可以包含 1..4 个订单项目。在一个订单中,可以有一种货币(这样的订单由 1..2 个订单项目组成)或两种货币(这样的订单由 2..4 个订单项目组成)。
我需要将其转换为订单表(即一行代表一个订单)。我是SQL window functions 的新手,所以任何提示都将不胜感激。
示例
原始数据结构:
| order_id |产品类型 |金额 |货币 | | 1 |一个 | 2 |美元 | | 1 |一个 | 1 |欧元 | | 1 |乙| 6 |美元 | | 1 |乙| 5 |欧元 | | 2 |一个 | 7 |美元 | | 2 |乙| 5 |美元 | | 2 |乙| 3 |加元 | | 3 |一个 | 2 |美元 | | 3 |乙| 4 |澳元 | | 4 |一个 | 1 |新西兰元 | | 4 |乙| 2 |新西兰元 | | 5 |一个 | 8 |欧元 |目标数据结构:
| order_id | a_amount1 | a_cur1 | a_amount2 | a_cur2 | b_amount1 | b_cur1 | b_amount2 | b_cur2 | | 1 | 2 |美元 | 1 |欧元 | 6 |美元 | 5 |欧元 | | 2 | 7 |美元 | | | 5 |美元 | 3 |加元 | | 3 | 2 |美元 | | | 4 |澳元 | | | | 4 | 1 |新西兰元 | | | 2 |新西兰元 | | | | 5 | 8 |欧元 | | | | | | |【问题讨论】:
【参考方案1】:我们可以尝试借助ROW_NUMBER
进行数据透视查询来生成用于区分货币的系列:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY order_id, product_type ORDER BY currency) rn
FROM yourTable
)
SELECT
order_id,
MAX(CASE WHEN product_type = 'A' AND rn = 1 THEN amount END) AS a_amount1,
MAX(CASE WHEN product_type = 'A' AND rn = 1 THEN currency END) AS a_cur1,
MAX(CASE WHEN product_type = 'A' AND rn = 2 THEN amount END) AS a_amount2,
MAX(CASE WHEN product_type = 'A' AND rn = 2 THEN currency END) AS a_cur2,
MAX(CASE WHEN product_type = 'B' AND rn = 1 THEN amount END) AS b_amount1,
MAX(CASE WHEN product_type = 'B' AND rn = 1 THEN currency END) AS b_cur1,
MAX(CASE WHEN product_type = 'B' AND rn = 2 THEN amount END) AS b_amount2,
MAX(CASE WHEN product_type = 'B' AND rn = 2 THEN currency END) AS b_cur2
FROM cte
GROUP BY
order_id
ORDER BY
order_id;
Demo
【讨论】:
只有一件小事:对于 product_type = 'B' 的情况,应该有 b_* 列别名。但逻辑工作正常,将使用更大的数据集进行进一步测试。谢谢蒂姆的精彩课程!以上是关于使用 SQL 将数据从行转换为列的主要内容,如果未能解决你的问题,请参考以下文章
pig - 将数据从行转换为列,同时为特定行中不存在的字段插入占位符