如何在 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 条路线。 这并没有解决问题 - 例如,为什么是 DELHI route4 而不是其他的?注意 - “因为这是我在屏幕上列出的方式”不适用。 表中的行没有定义的顺序。如果没有基于表中列的任何逻辑,就不可能知道 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 查询中将行转换为固定列的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql查询中将列更改为行

在 Spark SQL 中将 long 类型的列转换为 calendarinterval 类型

如何在 SQL 中将行转换为列值 [关闭]

如何在 SQL SERVER 中将内联 SQL 查询转换为 JOINS 以减少加载时间

如何在Oracle中将表行拆分为固定大小的块

如何在 SQL Server 或 C# 代码中将行转换为列