Транспонировать таблицы с сохранением идентификаторов - PullRequest
0 голосов
/ 18 сентября 2018

с трудом переносят таблицу, указанную ниже:

ID    Type  Col1  Col2  Col3
----------------------------
1     a      5     2     3
1     b      2     1     3
2     a      4     4     3
2     c      7     6     4

Результат должен выглядеть следующим образом:

ID    Col    a     b     c
----------------------------
1     Col1   5     2    null
1     Col2   2     1    null 
1     Col3   3     3    null
2     Col1   4    null   7
2     Col2   4    null   6
2     Col3   3    null   4

Здесь много похожих вопросов, но, похоже, ониЯ немного отличается от того, что мне нужно, потому что я хочу, чтобы идентификаторы были сохранены в наборе результатов.Пытался использовать расширение tablefunc без удачи.Есть мысли как это сделать?

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

db <> fiddle

SELECT 
    id, 
    key as col,
    max(value::int) FILTER (WHERE type = 'a') as a,
    max(value::int) FILTER (WHERE type = 'b') as b,
    max(value::int) FILTER (WHERE type = 'c') as c
FROM 
    table, 
    jsonb_each_text(
        jsonb_build_object('col1', col1, 'col2', col2, 'col3', col3)
    )
GROUP BY id, key
ORDER BY id, key

Основная идея состояла в том, что мне нужно перекрестное соединение трех столбцов (и их значений в виде пар ключ / значение) сстолбец id.Пара ключ / значение привела меня к идее JSON.С помощью функции JSON вы можете создать объект JSON (jsonb_build_object()):

id  type   col1   col2   col3   jsonb_build_object
1   a      5      2      3      {"col1": 5, "col2": 2, "col3": 3}
1   b      2      1      3      {"col1": 2, "col2": 1, "col3": 3}
2   a      4      4      3      {"col1": 4, "col2": 4, "col3": 3}
2   c      7      6      4      {"col1": 7, "col2": 6, "col3": 4}

С помощью jsonb_each_text вы можете развернуть объект JSON в одну строку для каждого элемента с дополнительным столбцом для ключа изначение (в виде текстовых столбцов):

id   type  (...)  key    value
1    a            col1   5
1    a            col2   2
1    a            col3   3
1    b            col1   2
1    b            col2   1
1    b            col3   3
2    a            col1   4
2    a            col2   4
2    a            col3   3
2    c            col1   7
2    c            col2   6
2    c            col3   4

Остальное - просто группировка и фильтрация (выполнение простого поворота).

0 голосов
/ 18 сентября 2018

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

ваши данные:

create temp table d(id int,type text,col1 int,col2 int ,col3 int);
insert into d values (1,'a',5,2,3),(1,'b',2,1,3),(2,'a',4,4,3),(2,'c',7,6,4);

один из способов сделать это - конвертировать в EAV, а затем сделать разворот на этом:

 with eav as (
   select id,type,'col1' as col,col1 as val from d
   union all
   select id,type,'col2',col2 from d
   union all
   select id,type,'col3',col3 from d) 
, ca as (select id,col, val from eav where type='a')
, cb as (select id,col, val from eav where type='b')
, cc as (select id,col, val from eav where type='c')
select id,col,ca.val as a ,cb.val as b, cc.val as c
 from ca 
 full outer join cb using (id,col)
 full outer join cc using (id,col)
 order by id,col;

результат: (после \pset null 'null' in psql)

 id | col  | a |  b   |  c   
----+------+---+------+------
  1 | col1 | 5 |    2 | null
  1 | col2 | 2 |    1 | null
  1 | col3 | 3 |    3 | null
  2 | col1 | 4 | null |    7
  2 | col2 | 4 | null |    6
  2 | col3 | 3 | null |    4

или это может быть устроено так:

with eav as (
   select id,type,'col1' as col,col1 as val from d
   union all
   select id,type,'col2',col2 from d
   union all
   select id,type,'col3',col3 from d) 
  , ca as (select id,col, val as a from eav where type='a')
  , cb as (select id,col, val as b from eav where type='b')
  , cc as (select id,col, val as c from eav where type='c')
 select *
  from ca 
  full outer join cb using (id,col)
  full outer join cc using (id,col)
  order by id,col;
...