首页 > 解决方案 > 动态将行转换为列

问题描述

我有这张表,条件是一个产品最多可以有 4 个标签(4 个标签名称/LN,4 个标签位置/LP):

PRODUCT_CODE    LABEL_NAME  PLACEMENT_DETAIL
---------------------------------------------
307960-010      Trademark   Bottom Left
307960-010      228119      Middle Left
307960-010      YCM Sticker Bottom Right
307960-015      Trademark   Bottom Left
307960-016      Trademark   Bottom Left
307960-017      Trademark   Bottom Left
307960-020      228119      Middle Left
307960-020      Trademark   Bottom Left

我想显示如下表格:

产品代码 LN1 LP1 LN2 LP2 LN3 LP3 LN4 LP4

307960-010 商标左下 228119 左中 YCM 贴纸右下 307960-015 商标左下角 307960-016 商标左下角 307960-017 商标左下角 307960-020 228119 左中商标左下

我尝试使用带有定义的标签名称或位置的 DECODE,但它与我想要的相差甚远,因为有超过 20 种标签,它的外观如下:

SELECT 
    PRODUCT_CODE,  
    DECODE(LABEL_NAME,'Trademark',label_name) AS "LN1", 
    DECODE(PLACEMENT_DETAIL,'Bottom Left',PLACEMENT_DETAIL) AS "LP1",
    DECODE(LABEL_NAME,'228119',label_name) AS "LN2", 
    DECODE(PLACEMENT_DETAIL,'Middle Left',PLACEMENT_DETAIL) AS "LP2",
    DECODE(LABEL_NAME,'YCM Sticker',label_name) AS "LN3", 
    DECODE(PLACEMENT_DETAIL,'Bottom Right',PLACEMENT_DETAIL) AS "LP3"
-- etc until all labels declared
FROM
    (SELECT   
         PPL.*,
         PML.LABEL_NAME
     FROM   
         MES.PL_PRODCODE_LABEL PPL, MES.PL_MASTER_LABEL PML  
     WHERE       
         PPL.ID_LABEL = PML.ID_LABEL
         AND PPL.STATUS_USE = 'Y'
         AND PML.STATUS_USE = 'Y'
     ORDER BY 2
)

结果如下:

PRODUCT_CODE LN1 LP1 LN2 LP2 LN3 LP3

307960-010 商标左下角 307960-010 228119 中左 307960-010 YCM 贴纸右下 307960-015 商标左下角 307960-016 商标左下角 307960-017 商标左下角 307960-020 228119 中左 307960-020 商标左下角

如何达到这样的效果?

谢谢你。

标签: oracleplsql

解决方案


你想PIVOT

row_number()在执行此操作之前,为每个产品代码 ( )分配一个起始值partition by product_code,根据您希望标签的优先级排序。

在该pivot子句中,对于产品的每个可能的条目数,取标签和位置的min(或):max

create table t (
  product_code varchar2(10),
  label_name   varchar2(20),
  placement    varchar2(20)
);

insert into t values ( '307960-010', 'Trademark', 'Bottom Left' );
insert into t values ( '307960-010', '228119', 'Middle Left' );
insert into t values ( '307960-010', 'YCM Sticker', 'Bottom Right' );
insert into t values ( '307960-015', 'Trademark', 'Bottom Left' );
insert into t values ( '307960-016', 'Trademark', 'Bottom Left' );
insert into t values ( '307960-017', 'Trademark', 'Bottom Left' );
insert into t values ( '307960-020', '228119', 'Middle Left' );
insert into t values ( '307960-020', 'Trademark', 'Bottom Left' );

with rws as (
  select t.*, 
         row_number () over (
           partition by product_code
           order by label_name, placement
         ) rn
  from   t
)
  select * from rws
  pivot (
    min ( label_name ) ln, min ( placement ) lp
    for rn in ( 1, 2, 3 )
  );
  
PRODUCT_CODE    1_LN         1_LP           2_LN         2_LP           3_LN           3_LP           
307960-010      228119       Middle Left    Trademark    Bottom Left    YCM Sticker    Bottom Right    
307960-015      Trademark    Bottom Left    <null>       <null>         <null>         <null>          
307960-016      Trademark    Bottom Left    <null>       <null>         <null>         <null>          
307960-017      Trademark    Bottom Left    <null>       <null>         <null>         <null>          
307960-020      228119       Middle Left    Trademark    Bottom Left    <null>         <null> 

推荐阅读