【问题标题】:Convert columns to rows in SQL [duplicate]在 SQL 中将列转换为行 [重复]
【发布时间】:2011-03-22 07:42:43
【问题描述】:

我需要编写一个查询,它接受行并将其转换为列 - 这是我的表:

Count    fname   lname   id
-----------------------------
1        abc     def    20
2        pqr            20      
3        abc     xyz    20  
4        xyz     xyz    20
1        abc     def    21
1        pqr     xyz    22
2        abc     abc    22

这是我试图产生的输出:

id  fname  lname  fname  lname  fname  lname  fname  lname
-------------------------------------------------------------
20  abc    def    pqr    NULL   abc    xyz    xyz    xyz
21  abc    def    NULL   NULL   NULL   NULL   NULL   NULL   
22  abc    abc    NULL   NULL   NULL   NULL   NULL   NULL

每个 id 的 count 最大值为 4。我使用的是 Oracle 9i。

【问题讨论】:

    标签: sql oracle plsql pivot oracle9i


    【解决方案1】:

    这是另一个你可能有运气的人。我喜欢@ThinkJet,但不确定解码成本是多少(如果多于或少于以下。

    SELECT
       T1.ID,
       T1.fname,
       T1.lname,
       T2.fname,
       T2.lname,
       T3.fname,
       T3.lname,
       T4.fname,
       T4.lname
    FROM
          table T1
       LEFT JOIN
          table T2
       ON
             T1.ID = T2.ID
          AND T2.count = 2
       LEFT JOIN
          table T3
       ON
             T1.ID = T3.ID
          AND T3.count = 3
       LEFT JOIN
          table T4
       ON
             T1.ID = T4.ID
          AND T4.count = 4
    WHERE
       T1.count = 1
    

    【讨论】:

      【解决方案2】:

      看这个例子,原理与@Mike M. 回答中的相同,但具有真正的 Oracle 实现:

        create table my_table (
          id    number,
          fname varchar2(255),
          lname varchar2(255),
          cnt   number
        );
      
        insert into my_table(cnt, fname, lname, id) values(1,'abc','def',20);
        insert into my_table(cnt, fname, lname, id) values(2,'pqr',''   ,20);      
        insert into my_table(cnt, fname, lname, id) values(3,'abc','xyz',20);  
        insert into my_table(cnt, fname, lname, id) values(4,'xyz','xyz',20);
        insert into my_table(cnt, fname, lname, id) values(1,'abc','def',21);
        insert into my_table(cnt, fname, lname, id) values(1,'pqr','xyz',22);
        insert into my_table(cnt, fname, lname, id) values(2,'abc','abc',22);
      
        select 
          tbl.id,
          min(decode(tbl.cnt, 1 , fname, null)) fname_1,
          min(decode(tbl.cnt, 1 , lname, null)) lname_1,
          min(decode(tbl.cnt, 2 , fname, null)) fname_2,
          min(decode(tbl.cnt, 2 , lname, null)) lname_2,
          min(decode(tbl.cnt, 3 , fname, null)) fname_3,
          min(decode(tbl.cnt, 3 , lname, null)) lname_3,
          min(decode(tbl.cnt, 4 , fname, null)) fname_4,
          min(decode(tbl.cnt, 4 , lname, null)) lname_4
        from 
          my_table tbl
        group by 
          tbl.id 
        order by 
          tbl.id  
        ;
      

      【讨论】:

        【解决方案3】:

        我知道您正在使用 Oracle 9i 解决方案,但 Oracle 11 引入了 PIVOT,它允许您执行以下查询:

        select *
          from mb_test
         pivot ( max(fname ) as fname,
                 max(lname) as lname
           for count in (1,2,3,4)
               )
        order by id
        ;
        

        给出:

         ID  1_fname  1_lname  2_fname  2_lname  3_fname  3_lname  4_fname  4_lname
        20  abc      def      pqr      null     abc      xyz      xyz      xyz
        21  abc      def      null     null     null     null     null     null
        22  pqr      xyz      abc      abc      null     null     null     null
        

        不完全是您所追求的,但在许多情况下非常有用....而且几乎值得单独升级 PIVOT 和 UNPIVOT

        编辑

        修改为将 fname 和 lname 放在不同的列中

        【讨论】:

        • 如题,fname 和 lname 必须是单独的列...
        • 查询和样本结果适当修改
        【解决方案4】:

        【讨论】:

        • 这是针对 SQL Server,而不是 Oracle。
        猜你喜欢
        • 1970-01-01
        • 2015-07-01
        • 2020-02-23
        • 2014-04-13
        • 1970-01-01
        • 2014-09-08
        • 2021-08-07
        • 2020-11-14
        • 1970-01-01
        相关资源
        最近更新 更多