SQL链接表并转换列

时间:2017-03-07 11:19:12

标签: sql oracle

我有两张桌子:

操作

opCode  opDescription  
001       DESC_01
002       DESC_02
003       DESC_03
004       DESC_04
..        ..

客户端

opCode  cliCode    clDescription  
001       C001         DESCR xx
001       C002         DESCR yy
002       C005         DESCR bb
002       C001         DESCR cc
002       C006         DESCR gg
002       C003         DESCR dd
..        ..           ..

我需要加入并转换列中的行

opCode   opDescription    cliCode1   clDescription1  cliCode2   clDescription2    cliCode3   clDescription3   .. ..  cliCode5   clDescription5 
001          DESC_01         C001       DESCRxx       C002       DESCRyy                   
002          DESC_02         C005       DESCRbb       C001       DESCRcc              C006      DESCRgg         C003      DESCRdd      

只能存在0到5个链接的客户

任何想法?

3 个答案:

答案 0 :(得分:2)

您可以使用row_number()和条件聚合:

执行此操作
select o.opcode, o.opDescription,
       max(case when seqnum = 1 then c.cliCode end) as cliCode1,
       max(case when seqnum = 1 then c.clDescription end) as clDescription1,
       max(case when seqnum = 2 then c.cliCode end) as cliCode2,
       max(case when seqnum = 2 then c.clDescription end) as clDescription2,
       max(case when seqnum = 3 then c.cliCode end) as cliCode3,
       max(case when seqnum = 3 then c.clDescription end) as clDescription3,
       max(case when seqnum = 4 then c.cliCode end) as cliCode4,
       max(case when seqnum = 4 then c.clDescription end) as clDescription4,
       max(case when seqnum = 5 then c.cliCode end) as cliCode5,
       max(case when seqnum = 5 then c.clDescription end) as clDescription5
from operations o left join
     (select c.*,
             row_number() over (partition by opcode order by cliCode) as seqnum
      from clients c
     ) c
     on o.opcode = c.opcode
group by o.opcode, o.opDescription

答案 1 :(得分:0)

这是关于旋转的,一次只有两列:

WITH
-- input data, don't use in real query
operations(opcode,opdescription) AS (
          SELECT '001','DESC_01'
UNION ALL SELECT '002','DESC_02'
UNION ALL SELECT '003','DESC_03'
UNION ALL SELECT '004','DESC_04'
)
,
clients(opcode,clicode,cldescription) AS (
          SELECT '001','C001','DESCR xx'
UNION ALL SELECT '001','C002','DESCR yy'
UNION ALL SELECT '002','C005','DESCR bb'
UNION ALL SELECT '002','C001','DESCR cc'
UNION ALL SELECT '002','C006','DESCR gg'
UNION ALL SELECT '002','C003','DESCR dd'
)
-- end of input data, start real query just after here, using WITH, not comma
,
join_with_sequence AS (
SELECT
  ROW_NUMBER() OVER(PARTITION BY o.opcode ORDER BY clicode) AS seq
, o.opcode
, o.opdescription
, clicode
, cldescription
FROM operations o
JOIN clients USING(opcode)
)
SELECT
  opcode
, opdescription
, MAX(CASE seq WHEN 1 THEN clicode       END) AS clicode1
, MAX(CASE seq WHEN 1 THEN cldescription END) AS cldescription1
, MAX(CASE seq WHEN 2 THEN clicode       END) AS clicode2
, MAX(CASE seq WHEN 2 THEN cldescription END) AS cldescription2
, MAX(CASE seq WHEN 3 THEN clicode       END) AS clicode3
, MAX(CASE seq WHEN 3 THEN cldescription END) AS cldescription3
, MAX(CASE seq WHEN 4 THEN clicode       END) AS clicode4
, MAX(CASE seq WHEN 4 THEN cldescription END) AS cldescription4
, MAX(CASE seq WHEN 5 THEN clicode       END) AS clicode5
, MAX(CASE seq WHEN 5 THEN cldescription END) AS cldescription5
FROM join_with_sequence
GROUP BY
  opcode
, opdescription
ORDER BY
  opcode
, opdescription
;
opcode|opdescription|clicode1|cldescription1|clicode2|cldescription2|clicode3|cldescription3|clicode4|cldescription4|clicode5|cldescription5
001   |DESC_01      |C001    |DESCR xx      |C002    |DESCR yy      |-       |-             |-       |-             |-       |-
002   |DESC_02      |C001    |DESCR cc      |C003    |DESCR dd      |C005    |DESCR bb      |C006    |DESCR gg      |-       |-

答案 2 :(得分:0)

或者,使用其中一个答案并使用Oracles pivot子句......

WITH
-- input data, don't use in real query
operations(opcode,opdescription) AS (
          SELECT '001','DESC_01' from dual
UNION ALL SELECT '002','DESC_02' from dual
UNION ALL SELECT '003','DESC_03' from dual
UNION ALL SELECT '004','DESC_04' from dual
)
,
clients(opcode,clicode,cldescription) AS (
          SELECT '001','C001','DESCR xx' from dual
UNION ALL SELECT '001','C002','DESCR yy' from dual
UNION ALL SELECT '002','C005','DESCR bb' from dual
UNION ALL SELECT '002','C001','DESCR cc' from dual
UNION ALL SELECT '002','C006','DESCR gg' from dual
UNION ALL SELECT '002','C003','DESCR dd' from dual
)
-- end of input data, start real query just after here, using WITH, not comma
,
join_with_sequence AS (
SELECT
  ROW_NUMBER() OVER(PARTITION BY o.opcode ORDER BY clicode) AS seq
, o.opcode
, o.opdescription
, clicode
, cldescription
FROM operations o
INNER JOIN clients ON (o.opcode = clients.opcode)
)
select * from join_with_sequence
pivot
(
 min(cliCode) as cliCode,
 min(clDescription) as clDescription
 FOR(seq) in (1 as cl1,2 as cl2,3 as cl3,4 as cl4,5 as cl5)
);