#postgresql #jsonb
#postgresql #jsonb
Вопрос:
jsonb_build_object('a',a, 'b',b)
является избыточным (не «автоматическим») и to_jsonb(row(a,b))
уродливым, потому что игнорирует имена столбцов… Неужели нет способа поступить правильно?
Примечания
Типичный запрос — это что-то вроде
SELECT a,b, record_to_jsonb(c,d,e) as info FROM t
Мне нужно динамическое решение, но, чтобы проиллюстрировать, статическим решением является определение типа данных,
CREATE TYPE mytest AS (c text, d int, e boolean);
SELECT a,b, to_jsonb(row(c,d,e)::mytest) as info FROM t; -- work fine!
PS: почему PostgreSQL не предлагает обратное jsonb_to_record()
?
Либо я не вижу элегантного и эффективного способа использования to_jsonb
(наиболее вероятного), либо, возможно, разработчики PostgreSQL забыли концепцию ортогональности библиотечных функций… Нет никаких технических проблем для реализации хорошей record_to_jsonb()
функции, как было продемонстрировано ранее такими функциями, как xmlattributes(a,b)
, которая фиксирует имя и значение colunm.
Комментарии:
1. Обратное просто
to_jsonb
вызывается с записью. (Проблема скорее в том, чтоrow()
конструктор не позволяет вам выбирать имена столбцов —to_jsonb
отлично работает со строками всей таблицы). Можете ли вы показать полный запрос, с которым вы работаете?2. Привет @Bergi Я отредактировал с помощью обычного запроса… Можете ли вы проиллюстрировать запрос, возможно, какое-то БОКОВОЕ СОЕДИНЕНИЕ, чтобы использовать ваше предложение?
3. Пожалуйста, прокомментируйте отрицательные голоса
4. Для динамического решения, в котором вы хотели бы выбрать имена атрибутов (точно так же, как с
xmlattributes
), которые вы действительно использовалиjsonb_build_object
бы. Я не вижу в этом ничего плохого. На самом деле проблема не в отсутствииto_jsonb
функциональности, а в том, что в postgres нет простого способа создавать произвольные записи с красивыми именами столбцов.5. вместо
to_jsonb(row(a,b))
того, чтобы просто использоватьselect to_jsonb(r) from (select a,b from ..) r
Ответ №1:
select a, b, to_jsonb(subq) as info
from t
cross join lateral (values (c, d, e)) as subq(c, d, e);
или короче, сокращая синтаксис ПЕРЕКРЕСТНОГО СОЕДИНЕНИЯ и используя предложение SELECT напрямую
select a, b, to_jsonb(subq) as info
from t, lateral (select c, d, e) subq;
Может ли что-то подобное больше соответствовать вашему варианту использования? Моя мысль состояла бы в том, чтобы сохранить a
and b
в json и позволить запрашивающему коду просто игнорировать его.
select a, b, to_jsonb(t) - 'a' - 'b' as info
from t
Комментарии:
1. Привет, Майк, запрос работает нормально (!) и, возможно, оптимизирован компилятором SQL, но это не решение проблемы PostgreSQL, это не «простой способ» для программиста выразить запрос и иметь ту же избыточность
jsonb_build_object('c',c, 'd',d, 'e',e)
, что и… Итак, программисты предпочтут jsonb_build_object, не так ли?2. PS: тестирование с
explain analyse
такой же производительностью (интересно!) там и .to_jsonb( row(c,d,e)::dtype )
jsonb_build_object('c',c, 'd',d, 'e',e)
3. @PeterKrauss Я понимаю вашу точку зрения и добавил еще одну возможность к моему ответу.
4. Синтаксис нового решения элегантен для дополнения столбцов (!), Но затраты на производительность высоки (JSONb медленно переделывает свою структуру)… Для не дополнения и производительности лучше использовать jsonb_build_object . Я добавил в ваше первоначальное решение альтернативный синтаксис с предложением SELECT, который кажется наиболее элегантным и эффективным : правильное решение вопроса.