【问题标题】:Oracle SQL: Transform rows to multiple columnsOracle SQL:将行转换为多列
【发布时间】:2015-04-13 21:06:25
【问题描述】:

我正在使用 Oracle 11G,需要一种方法在 select 语句中将行转换为新的列组。我们正在将一些数据转换为 1:3 关系,并且需要一种方法将其放入视图中。您能帮我们转换如下所示的数据吗:

+---------+------------+
| User_Id | Station_Id |  
+---------+------------+  
|       1 |        203 |
|       1 |        204 |
|       2 |        203 |
|       3 |        487 |
|       3 |       3787 |
|       3 |        738 |
+---------+------------+

进入这个:

+---------+-------------+-------------+---------------+
| User_Id | Station_One | Station_Two | Station_Three |
+---------+-------------+-------------+---------------+
|       1 |         203 | 204         | Null          |
|       2 |         203 | Null        | Null          |
|       3 |         487 | 3787        | 738           |
+---------+-------------+-------------+---------------+

让我知道您想要的其他细节,并感谢您提供的任何帮助!

【问题讨论】:

    标签: sql oracle oracle11g pivot


    【解决方案1】:

    您可以使用row_numberself joins

    with cte as 
    (
     select userid, stationid,
            row_number() over(partition by userid order by stationid) rn
     from tbl
    )
    
    select distinct c1.userid,
                    c1.stationid station_one,
                    c2.stationid station_two,
                    c3.stationid station_three 
    from cte c1
    left join cte c2 on c1.userid=c2.userid and c2.rn=2
    left join cte c3 on c1.userid=c3.userid and c3.rn=3
    where c1.rn=1
    

    the demo

    您也可以使用row_numbersubqueries

    with cte as 
    (
     select userid, stationid,
            row_number() over(partition by userid order by stationid) rn
     from tbl
    )
    
    select distinct userid, 
           (select stationid from cte c where c.userid=cte.userid and c.rn=1) station_one,
           (select stationid from cte c where c.userid=cte.userid and c.rn=2) station_two,
           (select stationid from cte c where c.userid=cte.userid and c.rn=3) station_three
    from cte
    

    the demo

    【讨论】:

      【解决方案2】:

      根据我的经验,最简单的方法是使用条件聚合:

      WITH mydata AS (
          SELECT 1 AS user_id, 203 AS station_id FROM dual
           UNION ALL
          SELECT 1 AS user_id, 204 AS station_id FROM dual
           UNION ALL
          SELECT 2 AS user_id, 203 AS station_id FROM dual
           UNION ALL
          SELECT 3 AS user_id, 487 AS station_id FROM dual
           UNION ALL
          SELECT 3 AS user_id, 3787 AS station_id FROM dual
           UNION ALL
          SELECT 3 AS user_id, 738 AS station_id FROM dual
      )
      SELECT user_id
           , MAX(CASE WHEN rn = 1 THEN station_id END) AS station_one
           , MAX(CASE WHEN rn = 2 THEN station_id END) AS station_two
           , MAX(CASE WHEN rn = 3 THEN station_id END) AS station_three
        FROM (
          SELECT user_id, station_id, ROW_NUMBER() OVER ( PARTITION BY user_id ORDER BY rownum ) AS rn
            FROM mydata
      ) GROUP BY user_id;
      

      只需将上述查询中的mydata CTE 替换为您的表名即可:

      SELECT user_id
           , MAX(CASE WHEN rn = 1 THEN station_id END) AS station_one
           , MAX(CASE WHEN rn = 2 THEN station_id END) AS station_two
           , MAX(CASE WHEN rn = 3 THEN station_id END) AS station_three
        FROM (
          SELECT user_id, station_id, ROW_NUMBER() OVER ( PARTITION BY user_id ORDER BY rownum ) AS rn
            FROM mytable
      ) GROUP BY user_id;
      

      【讨论】:

      • 嗨,大卫,感谢您的回复。抱歉,我在最初的问题中没有更具体。有数千个站 ID,因此您的解决方案对于我的目的来说不够动态。
      • 我不确定我是否理解我的回答不够动态 - 它与您接受的答案一样动态。
      猜你喜欢
      • 2020-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多