具有扭曲的转置表:在同一行上聚合相似的字段

时间:2014-11-25 09:17:28

标签: plsql oracle11g oracle-sqldeveloper

我一直在寻找以下问题的答案(如果这是转发,请原谅我,但我真的对这个问题感到疯狂)。

我在客户R1, R2, R3, R4, R5和人AAA, BBB, CCC, DDD之间有以下关系表XXX,YYY,ZZZ

relation_id   client  in_relation_with  relation_type
---           ---     ---               ---
1             AAA     XXX               R1
2             AAA     YYY               R1
3             AAA     ZZZ               R3
4             BBB     XXX               R2
5             BBB     YYY               R5
6             CCC     XXX               R2
7             DDD     ZZZ               R4
8             DDD     YYY               R4
9             DDD     XXX               R4

我想有下表:

client  R1.1      R1.2      R2       R3       R4.1     R4.2    R4.3    R5
---     ---       ---       ---      ---      ---      ---     ---     ---
AAA     XXX       YYY       -        ZZZ      -        -       -       -
BBB     -         -         XXX      -        -        -       -       YYY
CCC     -         -         XXX      -        -        -       -       -
DDD     -         -         -        -        XXX      YYY     ZZZ     -

问题是客户端(DDD)可以与不同的人(R4)具有相似的关系(类型XXX, YYY, ZZZ)以及与我们的客户所在的人数相同relation with是一个先验未知但可以在max表上找到relations语句。 困难的部分是提出这些R1.1, R1.2, R4.1...列和null,其中没有任何关系(至少对我而言)......

PL / SQL中是否完全可以使用?

非常感谢!

干杯

2 个答案:

答案 0 :(得分:1)

我可以考虑类似下面的解决方案,可以将其更改为解析分隔符分隔值以将它们转换为列。

with relations as (select 1 relation_id, 'AAA' client, 'XXX' in_relation_with, 'R1' relation_type
                      from dual
                    union all
                    select 2, 'AAA', 'YYY', 'R1'
                      from dual
                    union all
                    select 3, 'AAA', 'ZZZ', 'R3'
                      from dual
                    union all
                    select 4, 'BBB', 'XXX', 'R2'
                      from dual
                    union all
                    select 5, 'BBB', 'YYY', 'R5'
                      from dual
                    union all
                    select 6, 'CCC', 'XXX', 'R2'
                      from dual
                    union all
                    select 7, 'DDD', 'ZZZ', 'R4'
                      from dual
                    union all
                    select 8, 'DDD', 'YYY', 'R4'
                      from dual
                    union all
                    select 9, 'DDD', 'XXX', 'R4'
                      from dual
                    )
select *       
  from relations
pivot
(
listagg(in_relation_with, ',') within group(order by relation_id)
for relation_type in ('R1' as r1, 'R2' as r2, 'R3' as r3, 'R4' as r4, 'R5' as r5)
)

希望这会对你有所帮助。

答案 1 :(得分:0)

这是代码。另请参阅here了解小提琴

select 
  client,
  case when instr(r1, ',')>=1 then regexp_substr(r1,'[^,]+',1,1) else r1   end r1_1,
  case when instr(r1, ',')>=1 then regexp_substr(r1,'[^,]+',1,2) else null end r1_2,
  r2,
  r3,
  case when instr(r4, ',')>=1 then regexp_substr(r4,'[^,]+',1,1) else r1   end r1_1,
  case when instr(r4, ',')>=1 then regexp_substr(r4,'[^,]+',1,2) else null end r4_2,
  case when instr(r4, ',')>=1 then regexp_substr(r4,'[^,]+',1,3) else null end r4_3,
  r5
  from( 
    with relations as (
      select 1 relation_id, 'AAA' client, 'XXX' in_relation_with, 'R1' relation_type from dual union all
      select 2            , 'AAA'       , 'YYY'                 , 'R1'               from dual union all
      select 3            , 'AAA'       , 'ZZZ'                 , 'R3'               from dual union all
      select 4            , 'BBB'       , 'XXX'                 , 'R2'               from dual union all
      select 5            , 'BBB'       , 'YYY'                 , 'R5'               from dual union all
      select 6            , 'CCC'       , 'XXX'                 , 'R2'               from dual union all
      select 7            , 'DDD'       , 'ZZZ'                 , 'R4'               from dual union all
      select 8            , 'DDD'       , 'YYY'                 , 'R4'               from dual union all
      select 9            , 'DDD'       , 'XXX'                 , 'R4'               from dual
    )
      select *       
        from relations
        pivot(
          listagg(in_relation_with, ',') 
          within group(order by relation_id)
          for relation_type in ('R1' as r1, 'R2' as r2, 'R3' as r3, 'R4' as r4, 'R5' as r5)
        )
  );