首页 > 解决方案 > SQL:将宽表转换为窄表

问题描述

我有一个表,其中每一行都有一些布尔字段,如下所示:

user_id          | USD | EUR | CAD | ....
               1 |   1 |   1 |   0 | ....
               2 |   0 |   1 |   1 | ....

我需要把它转换成这样的东西:

user_id          | currency
               1 | USD
               1 | EUR
               2 | EUR
               2 | CAD

我设法用大量的 UNION(每种货币一个)构建了一个丑陋的 SQL,但我觉得这不是最好的方法。帮助任何人?

PS 此查询将在 AWS Athena 上执行,因此我担心成本,我希望对此进行最优化的查询。

标签: sqlprestoamazon-athenaunpivot

解决方案


如果您的数据库支持横向连接和values()行构造函数,那么您可以执行以下操作:

select x.user_id, x.currency
from mytable t
cross join lateral (values(user_id, 'USD', usd), (user_id, 'EUR', eur), (user_id, 'CAD', cad)) x(user_id, currency, val)
where x.val= 1

cross apply一些数据库使用而不是实现横向连接cross join lateral

一种更便携的方法是union all. 这效率较低,因为它需要多次表扫描:

select user_id, 'USD'currency from mytable where usd = 1
union all select user_id, 'EUR' from mytable where eur = 1
union all select user_id, 'CAD' from mytable where cad = 1

推荐阅读