Как превратить строки с повторяющимися значениями в столбцы? - PullRequest
0 голосов
/ 30 ноября 2018

Я пытаюсь развернуть таблицу, но сохраняю дополнительные строки (в моем примере, eeeeee). Есть ли способ в Oracle SQL сделать это?

select * from (
select 
    mat_table.material, attribute_table.attribute, attribute_table.value
  from 
    mat_table mat_table
    inner join 
    attribute_table on mat_table.rel= attribute_table.rel
    where 




      material = 'Material_A' 
            )


material    |attribute|  value
_____________________________________

Material_A  |aaaaaa    | 
Material_A  |bbbbbb    |       hello
Material_A  |cccccc    |       val_1
Material_A  |dddddd    |       2
Material_A  |eeeeee    |       15
Material_A  |eeeeee    |       16
Material_A  |eeeeee    |       24 

, когда я использую сводку в предложении where

    pivot (
    max(attribute) as max_value for attribute IN ( 'aaaaaa', 
                                                   'bbbbbb', 
                                                   'cccccc', 
                                                   'dddddd', 
                                                   'eeeeee'
                                      ))

Я приближаюсь к тому, что хочу, но для eeeee я получаю только одно значение

material    |aaaaaa | bbbbbb | cccccc | dddddd | eeeeee |
__________________________________________________________
Material_A  |       | hello  | val_1  | 2      | 24     |

, но я хочу что-то вроде

material    |aaaaaa | bbbbbb | cccccc | dddddd | eeeeee_1 | eeeeee_2 | eeeeee_3 |
   __________________________________________________________________________________
Material_A  |       | hello  | val_1  | 2      | 15            16    |     24

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

РЕДАКТИРОВАТЬ: TS отметил, что он не работает для нескольких материалов.Поэтому я расширил ответ, чтобы учесть это.

Вы можете просто объединить row_number (разделенный на материал, атрибут) к атрибуту в вашем первом запросе.Вы можете добавить порядок по значению, если хотите.Чтобы учесть несколько материалов, row_number также должен быть разделен по материалам.Это означает, что одинаковые атрибуты для разных материалов получат одинаковое имя и окажутся в одном столбце.

заменить attribute_table.attribute на

concat(attribute_table.attribute,'_', row_number() over (partition by attribute_table.material, attribute_table.attribute order by attribute_table.attribute, attribute_table.value))

Полный код и результат:

with mat_table  as
  (
  select 'Material_A' as material, 'aaaaaa' as attribute, null as value
  union all select 'Material_A', 'bbbbbb', 'hello' 
  union all select 'Material_A', 'cccccc', 'val_1' 
  union all select 'Material_A', 'dddddd', '2' 
  union all select 'Material_A', 'eeeeee', '15' 
  union all select 'Material_A', 'eeeeee', '16' 
  union all select 'Material_A', 'eeeeee', '24' 
  union all select 'Material_B' , 'aaaaaa', 'lol' 
  union all select 'Material_B', 'bbbbbb', 'hi' 
  union all select 'Material_B', 'cccccc', 'max_val' 
  union all select 'Material_B', 'dddddd', '4' 
  union all select 'Material_B', 'eeeeee', '67' 
  union all select 'Material_B', 'eeeeee', '99' 
  union all select 'Material_B', 'eeeeee', null
  )

select *
from (
    select t.material,
            t.value ,
            concat(t.attribute,'_', row_number() over (partition by t.material , t.attribute order by t.attribute, t.value)) as numbered_attribute
    from mat_table t) as d
pivot (
    max(d.value)  
    for numbered_attribute IN ( [aaaaaa_1],  
                                [bbbbbb_1], 
                                [cccccc_1], 
                                [dddddd_1], 
                                [eeeeee_1],
                                [eeeeee_2],
                                [eeeeee_3]
                             )) as total
    order by total.material

Примечание. Я использовал SQL-сервер.Возможно, вам придется изменить синтаксис, например [eeeeee_3] => 'eeeeee_3'

Базовая таблица с пронумерованными атрибутами:

base table

Окончательный результат после разворота:

final result

0 голосов
/ 06 декабря 2018

Если всегда есть 3 значения для eeeeee, тогда вы можете сделать это следующим образом

SQL> with mat_table (material, attribute, value) as
  2  (
  3  select 'Material_A', 'aaaaaa', null from dual
  4  union all select 'Material_A', 'bbbbbb', 'hello' from dual
  5  union all select 'Material_A', 'cccccc', 'val_1' from dual
  6  union all select 'Material_A', 'dddddd', '2' from dual
  7  union all select 'Material_A', 'eeeeee', '15' from dual
  8  union all select 'Material_A', 'eeeeee', '16' from dual
  9  union all select 'Material_A', 'eeeeee', '24' from dual
 10  )
 11  select *
 12    from (select t.*,
 13                 row_number() over(partition by attribute order by value) rn
 14            from mat_table t)
 15  pivot (max(value) for (attribute, rn) in
 16  (
 17   ('aaaaaa', 1), ('bbbbbb', 1), ('cccccc', 1), ('dddddd', 1),
 18   ('eeeeee', 1), ('eeeeee', 2), ('eeeeee', 3)
 19  ));

MATERIAL   'aaaa 'bbbb 'cccc 'dddd 'eeee 'eeee 'eeee
---------- ----- ----- ----- ----- ----- ----- -----
Material_A       hello val_1 2     15    16    24

Если, однако, вы ожидаете, что Oracle будет динамически создавать столбцы для любого количества значений для eeeeee, тогдаэто невозможно.

Пожалуйста, прочитайте подробное объяснение здесь Oracle Dynamic Pivoting

Вы можете генерировать XML для любых комбинаций attribute и value, но если хотитечтобы отобразить результат с использованием SQL, в конечном итоге все столбцы должны быть указаны (альтернативный подход - синтаксический анализ XML на стороне клиента).

SQL> with mat_table (material, attribute, value) as
  2  (
  3  select 'Material_A', 'aaaaaa', null from dual
  4  union all select 'Material_A', 'bbbbbb', 'hello' from dual
  5  union all select 'Material_A', 'cccccc', 'val_1' from dual
  6  union all select 'Material_A', 'dddddd', '2' from dual
  7  union all select 'Material_A', 'eeeeee', '15' from dual
  8  union all select 'Material_A', 'eeeeee', '16' from dual
  9  union all select 'Material_A', 'eeeeee', '24' from dual
 10  )
 11  select material, x.*
 12  from mat_table
 13  pivot xml (count(*) as dummy for (attribute, value) in (any, any))
 14  -- parsing output
 15  , xmltable('/PivotSet' passing attribute_value_xml
 16             columns
 17               aaaaaa varchar2(10) path '/PivotSet/item[column="aaaaaa"]/column[2]',
 18               bbbbbb varchar2(10) path '/PivotSet/item[column="bbbbbb"]/column[2]',
 19               cccccc varchar2(10) path '/PivotSet/item[column="cccccc"]/column[2]',
 20               dddddd varchar2(10) path '/PivotSet/item[column="dddddd"]/column[2]',
 21               eeeeee_1 varchar2(10) path '/PivotSet/item[column="eeeeee"][1]/column[2]',
 22               eeeeee_2 varchar2(10) path '/PivotSet/item[column="eeeeee"][2]/column[2]',
 23               eeeeee_3 varchar2(10) path '/PivotSet/item[column="eeeeee"][3]/column[2]') x;

MATERIAL   AAAAAA     BBBBBB     CCCCCC     DDDDDD     EEEEEE_1   EEEEEE_2   EEEEEE_3
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
Material_A            hello      val_1      2          15         16         24

В этом случае нет гарантии, что EEEEEE_1 / EEEEEE_2 / EEEEEE_3 будетбыть 15/16/24 именно в таком порядке.

...