oracle 11g中有多行到多个列

时间:2015-03-05 20:29:03

标签: sql oracle oracle11g

我有两个看起来像这样的表:

table1

id  rs_id               
1   1001                
2   2001

table2

rs_id   rs_name             
1001    aaa             
1001    bbb             
2001    aaa             
2001    bbb             
2001    ccc     

期望的输出:

id  rs_id   rs_name1    rs_name2    rs_name3    rs_name4
1   1001    aaa         bbb     
2   2001    aaa         bbb         ccc 

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

假设您知道列数,您基本上试图pivot您的结果。一种选择是使用条件聚合。但是,您没有要聚合的字段。

以下是使用row_number()创建此类字段的一种方法:

select id, 
    rs_id, 
    max(case when rn = 1 then rs_name end) rs_name_1,
    max(case when rn = 2 then rs_name end) rs_name_2,
    max(case when rn = 3 then rs_name end) rs_name_3,
    max(case when rn = 4 then rs_name end) rs_name_4
from (
    select t1.id, 
          t1.rs_id, 
          t2.rs_name, 
          row_number() over (partition by t1.id, t1.rs_id order by t2.rs_name) rn
    from table1 t1
        join table2 t2 on t1.rs_id = t2.rs_id
) t
group by id, rs_id

如果您不知道列数,则需要使用动态SQL来构建列表。

答案 1 :(得分:0)

这是一个适用于Oracle 10g和Oracle 11g的解决方案。我假设你的最大列数为4.类似的解决方案可以用PIVOT计算出来;如果你想要一个动态解决方案,那么你需要使用PL / SQL。

SELECT id, rs_id
     , MAX(CASE WHEN rn = 1 THEN rs_name END) AS rs_name1
     , MAX(CASE WHEN rn = 2 THEN rs_name END) AS rs_name2
     , MAX(CASE WHEN rn = 3 THEN rs_name END) AS rs_name3
     , MAX(CASE WHEN rn = 4 THEN rs_name END) AS rs_name4
  FROM (
    SELECT t1.id, t1.rs_id, t2.rs_name, ROW_NUMBER() OVER ( PARTITION BY t1.id ORDER BY t2.rs_name ) AS rn
      FROM table1 t1 INNER JOIN table2 t2
        ON t1.rs_id = t2.rs_id
) GROUP BY id, rs_id;

答案 2 :(得分:0)

第一个解决方案:

SELECT id, rs_id
     , MAX(CASE WHEN rn = 1 THEN rs_name END) AS rs_name1
     , MAX(CASE WHEN rn = 2 THEN rs_name END) AS rs_name2
     , MAX(CASE WHEN rn = 3 THEN rs_name END) AS rs_name3
     , MAX(CASE WHEN rn = 4 THEN rs_name END) AS rs_name4
  FROM (
    SELECT t1.id, t1.rs_id, t2.rs_name, ROW_NUMBER() OVER ( PARTITION BY t1.id ORDER BY t2.rs_name ) AS rn
      FROM table1 t1 INNER JOIN table2 t2
        ON t1.rs_id = t2.rs_id
) GROUP BY id, rs_id;

第二个解决方案:

SELECT  id, rs_id,
        REGEXP_SUBSTR (rsname_list, '[^,]+', 1, 1)    AS rs_name1,
        REGEXP_SUBSTR (rsname_list, '[^,]+', 1, 2)    AS rs_name2,
        REGEXP_SUBSTR (rsname_list, '[^,]+', 1, 3)    AS rs_name3,
        REGEXP_SUBSTR (rsname_list, '[^,]+', 1, 4)    AS rs_name4
FROM
(
SELECT a.id,
       a.rs_id,
       LISTAGG (
          b.rs_name, ','
       ) WITHIN GROUP (
          ORDER BY b.rs_name
       ) AS rsname_list
  FROM test_table1 a
  LEFT JOIN test_table2 b ON a.rs_id = b.rs_id
 GROUP BY a.id,a.rs_id
 ORDER BY a.rs_id
 );