Динамически преобразовывать строки в столбец

#oracle #plsql

#Oracle #plsql

Вопрос:

У меня есть эта таблица с условием, что у одного продукта может быть до 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 Торговая марка внизу слева

Как добиться такого результата?

Спасибо.

Комментарии:

1. Вредные привычки: использование объединений в старом стиле — этот стиль списка таблиц, разделенных запятыми , в старом стиле был заменен соответствующим JOIN синтаксисом ANSI в стандарте SQL ANSI- 92 ( более 25 лет назад), и его использование не рекомендуется

2. спасибо, я буду иметь в виду, чтобы избежать объединения в старом стиле.

Ответ №1:

Вы хотите свернуть

Прежде чем делать это, назначьте 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> 
  

Комментарии:

1. Отлично, теперь он показывает то, что я хотел. Спасибо, сэр, мне нужно узнать больше., хорошего дня.