如何在 SQL 查询中将行转换为固定列
Posted
技术标签:
【中文标题】如何在 SQL 查询中将行转换为固定列【英文标题】:How do I turn Rows to fixed Columns in SQL query 【发布时间】:2022-01-10 22:52:00 【问题描述】:您好,请帮助我完成以下查询: 我目前的数据表如下。
flight_id | route |
---|---|
1 | BAHRAIN |
2 | VIENNA |
2 | DUBAI |
3 | DUBAI |
3 | COCHIN |
3 | DOHA |
3 | COLOMBO |
4 | LONDON |
4 | MOSCOW |
4 | CHENNAI |
4 | DELHI |
4 | VNUKOVO |
4 | DUBAI |
我想将我的数据表转换为以下格式。我认为它类似于 Pivot,但不知道该怎么做。 :)
flight_id | route1 | route2 | route3 | route4 | route5 | route6 |
---|---|---|---|---|---|---|
1 | BAHRAIN | N/A | N/A | N/A | N/A | N/A |
2 | VIENNA | DUBAI | N/A | N/A | N/A | N/A |
3 | DUBAI | COCHIN | DOHA | COLOMBO | N/A | N/A |
4 | LONDON | MOSCOW | CHENNAI | DELHI | VNUKOVO | DUBAI |
请帮帮我!
谢谢!
【问题讨论】:
你判断哪个城市属于路线 N 的逻辑是什么? N/A in some routes 表示该航线没有数据,例如flight_id 1只有一条航线,选择route1和flight_id 4有6条航线id 将在整个 6 条路线中选择。我想选择最多 6 条路线。 这并没有解决问题 - 例如,为什么是 DELHIroute4
而不是其他的?注意 - “因为这是我在屏幕上列出的方式”不适用。
表中的行没有定义的顺序。如果没有基于表中列的任何逻辑,就不可能知道 4 号航班从伦敦“开始”并继续以特定顺序飞往莫斯科,然后是钦奈等。也许这并不重要,您也不关心如何为任何航班订购“路线”。这种想法通常非常罕见。
【参考方案1】:
这里有一个支点替代方案。
无需担心 order by (select null) 子句read about this here,但您必须设置一些字段以保持顺序。
select * from
(
select
[flight_id],
[route],
concat('route',
(row_number() over (partition by [flight_id] order by (select null)))
) [routeId]
from [routes]
) t
pivot
(
max([route])
for [routeId] in ([route1], [route2], [route3], [route4], [route5], [route6])
) p
-- result
/**
* +-----------+---------+--------+---------+---------+---------+--------+
* | flight_id | route1 | route2 | route3 | route4 | route5 | route6 |
* +-----------+---------+--------+---------+---------+---------+--------+
* | 1 | BAHRAIN | NULL | NULL | NULL | NULL | NULL |
* | 2 | VIENNA | DUBAI | NULL | NULL | NULL | NULL |
* | 3 | DUBAI | COCHIN | DOHA | COLOMBO | NULL | NULL |
* | 4 | LONDON | MOSCOW | CHENNAI | DELHI | VNUKOVO | DUBAI |
* +-----------+---------+--------+---------+---------+---------+--------+
*/
【讨论】:
【参考方案2】:解决方案通常是使用aggregated conditional case expression
。
我已按字母顺序排列城市以确定路线 1-6;如果您有不同的要求,请修改row_number
函数的order by
条件以使用相关列或表达式。
with r as (
select *, Row_Number() over(partition by flight_id order by route) rn
from flights
)
select
flight_id,
Max(case when rn = 1 then route end) Route1,
Max(case when rn = 2 then route end) Route2,
Max(case when rn = 3 then route end) Route3,
Max(case when rn = 4 then route end) Route4,
Max(case when rn = 5 then route end) Route5,
Max(case when rn = 6 then route end) Route6
from r
group by flight_Id
【讨论】:
以上是关于如何在 SQL 查询中将行转换为固定列的主要内容,如果未能解决你的问题,请参考以下文章
在 Spark SQL 中将 long 类型的列转换为 calendarinterval 类型