Psql | Как выбрать данные с именем столбца и отсортировать его значение как JSON - PullRequest
0 голосов
/ 31 марта 2020

Я использую postgreSQL 11 и ищу способ выбора и сортировки значений из столбца «деньги, обаяние, удача, остроумие, здоровье» и сгруппировать их под primaryAttr ( L & XL) или secondAttr (M) в соответствии с его значением.

Вот пример таблицы: [product]

| **id** |   price  |  money  | charm  |  luck  |  wit  | health |
|--------+----------+---------+--------+--------+-------+--------|
| 158001 |   1500   |    M    |   XL   |    L   |   M   |   M    |
| 158002 |   2000   |    L    |   M    |    M   |   XL  |   L    |

, и я хотел бы получить следующий результат: [product]

|     id    |   price   |               primary_attr                    |                   secondary_attr              |
|-----------+-----------+-----------------------------------------------+-----------------------------------------------|
|   158001  |   1500    |   {"luck": "L", "charm": "XL"}                |   {"wit": "M", "money": "M", "health": "M"}   |
|   158002  |   2000    |   {"wit": "XL", "money": "L", "health": "L"}  |   {"luck": "M", "charm": "M"}                 |

JSON результат:

{ 
  "id":"158001",
  "price":"1500",
  "primaryAttr": {
    "charm": "XL",
    "luck": "L"
  },
  "secondaryAttr": {
    "money": "M",
    "wit": "M",
    "health": "M"
  }
},
{ 
  "id":"158002",
  "price":"2000",
  "primaryAttr": {
    "money": "L",
    "wit": "XL",
    "health": "L"
  },
  "secondaryAttr":{
    "charm": "M",
    "luck": "M"
  }
}

Я искал решение, но пока не смог найти ничего подобного. Я пытаюсь собрать вещи вместе и посмотреть, есть ли какое-то хорошее решение для этого. Я буду помещать любые обновления здесь, как только я добился прогресса. Кто-нибудь сделал что-нибудь подобное, что могло бы указать мне правильное направление? Спасибо за помощь и советы!

данные настройки для тестирования Я забыл добавить это (спасибо @Oto Shavadze).

create table product(id int, price numeric, money text, charm text, luck text,  wit text, health text);
insert into product  
values 
(158001, 1500, 'M','XL','L','M','M'),
(158002, 2000, 'L','M','M','XL','L');

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Я думаю, вам нужно что-то вроде:

-- just setup  data 
create table product(
id int, 
price numeric, 
money text, 
charm text, 
luck text,  
wit text, 
health text
);

insert into product
values  
(158001 ,  1500   , 'M','XL','L','M','M'),
(158002 ,  2000   ,  'L','M','M','XL','L');

-- actual query:
select v from 
product
join  lateral 
 jsonb_build_object('id', id, 'price', price, 
    'primaryAttr', 
    case 
    when money in('XL','L') then jsonb_build_object('money', money) else '{}'::jsonb
    end ||
    case 
    when charm in('XL','L') then jsonb_build_object('charm', charm) else '{}'::jsonb
    end ||
    case 
    when luck in('XL','L') then jsonb_build_object('luck', luck) else '{}'::jsonb
    end ||
    case 
    when wit in('XL','L') then jsonb_build_object('wit', wit) else '{}'::jsonb
    end ||
    case 
    when health in('XL','L') then jsonb_build_object('health', health) else '{}'::jsonb
    end,

    'secondaryAttr', 
    case 
    when money in('M') then jsonb_build_object('money', money) else '{}'::jsonb
    end ||
    case 
    when charm in('M') then jsonb_build_object('charm', charm) else '{}'::jsonb
    end ||
    case 
    when luck in('M') then jsonb_build_object('luck', luck) else '{}'::jsonb
    end ||
    case 
    when wit in('M') then jsonb_build_object('wit', wit) else '{}'::jsonb
    end ||
    case 
    when health in('M') then jsonb_build_object('health', health) else '{}'::jsonb
    end
     ) j(v)
  on true;

РЕДАКТИРОВАТЬ

select id, price, 
case 
    when money in('XL','L') then jsonb_build_object('money', money) else '{}'::jsonb
    end ||
    case 
    when charm in('XL','L') then jsonb_build_object('charm', charm) else '{}'::jsonb
    end ||
    case 
    when luck in('XL','L') then jsonb_build_object('luck', luck) else '{}'::jsonb
    end ||
    case 
    when wit in('XL','L') then jsonb_build_object('wit', wit) else '{}'::jsonb
    end ||
    case 
    when health in('XL','L') then jsonb_build_object('health', health) else '{}'::jsonb
end as primaryAttr,
case 
    when money in('M') then jsonb_build_object('money', money) else '{}'::jsonb
    end ||
    case 
    when charm in('M') then jsonb_build_object('charm', charm) else '{}'::jsonb
    end ||
    case 
    when luck in('M') then jsonb_build_object('luck', luck) else '{}'::jsonb
    end ||
    case 
    when wit in('M') then jsonb_build_object('wit', wit) else '{}'::jsonb
    end ||
    case 
    when health in('M') then jsonb_build_object('health', health) else '{}'::jsonb
end as secondaryAttr
from 
product;

DEMO: https://rextester.com/AXYUL76207

0 голосов
/ 31 марта 2020

Хммм. Вы можете отключить и сгруппировать:

select t.id, t.price, a.*
from t cross join lateral
     (select array_agg(attr) filter (where val in ('L', 'XL')) as primaryAttr,
             array_agg(attr) filter (where val in ('M')) as secondaryAttr             
      from (values ('money', t.money), ('charm', t.charm), ('wit', t.wit), ('luck', t.luck), ('health', t.health)
           ) v(attr, val)
     ) a;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...