SQLRU.net
Разработка приложений баз данных

Начало » Использование СУБД » PostgreSQL » Массово заменить ключ в jsonb
Массово заменить ключ в jsonb [сообщение #6330] Wed, 08 April 2026 14:41 Переход к следующему сообщению
polin11 в настоящее время не в онлайне  polin11
Сообщений: 11
Зарегистрирован: January 2023
Junior Member
Использую PGSQL 16.

Есть основная таблица

CREATE TABLE product (
  doc_id INT,
  details JSONB
);


INSERT INTO product VALUES (1, '{"CPU":4, "RAM":16, "HDD":2}');
INSERT INTO product VALUES (2, '{"CPU":3, "RAM":8, "HDD":1}');


doc_id |             details             
----+---------------------------------
  1 | {"CPU": 4, "HDD": 2, "RAM": 16}
  2 | {"CPU": 3, "HDD": 1, "RAM": 8}
 
 
Также есть таблица соотв. для замены товара
CREATE TABLE replace (
  id INT,
  doc_id INT,
  old_key text,
  new_key text
);
INSERT INTO replace VALUES (1, 1, 'CPU', 'RAM');
INSERT INTO replace VALUES (2, 1, 'HDD', 'SSD');
INSERT INTO replace VALUES (3, 2, 'HDD', 'SSD');

id | doc_id | old_key | new_key 
----+--------+---------+---------
  1 |      1 | CPU     | RAM
  2 |      1 | HDD     | SSD
  3 |      2 | HDD     | SSD
 
Нужно в таблице product в JSONB заменить старый ключ на новый ключ, если новый ключ уже есть в JSONB, то значения
старого и нового ключей нужно сложить,
то есть после замены должны получить такие данные product:
id |             details             
----+---------------------------------
  1 | {"SSD": 2, "RAM": 20}
  2 | {"CPU": 3, "SSD": 1, "RAM": 8}
 
 
У меня нет идей как это можно сделать, помогите пож-ста написать такой запрос
 
Re: Массово заменить ключ в jsonb [сообщение #6344 является ответом на сообщение #6330] Fri, 01 May 2026 21:28 Переход к предыдущему сообщению
BlackEric в настоящее время не в онлайне  BlackEric
Сообщений: 394
Зарегистрирован: June 2022
Senior Member
WITH upd AS (
  SELECT
    p.doc_id,
    jsonb_object_agg(
      COALESCE(r.new_key, key),  -- если есть замена, берем new_key
      CASE
        WHEN r.new_key IS NOT NULL AND p.details ? r.new_key
          THEN ( (p.details ->> key)::int + (p.details ->> r.new_key)::int )::text::jsonb
        ELSE value
      END
    ) AS new_details
  FROM product p
  LEFT JOIN replace r
         ON p.doc_id = r.doc_id AND (p.details ? r.old_key)
  CROSS JOIN LATERAL jsonb_each(p.details)
  WHERE r.old_key IS NULL OR key = r.old_key
  GROUP BY p.doc_id
)
UPDATE product AS p
SET details = u.new_details
FROM upd u
WHERE p.doc_id = u.doc_id;
Предыдущая тема: JSONB преобразовать значения из строк в числа
Переход к форуму:
  


Текущее время: Fri May 01 23:21:22 GMT+3 2026

Общее время, затраченное на создание страницы: 0.00764 секунд