Как преобразовать тип PostgreSQL 9.4 jsonb в float
Я пробую следующий запрос:
SELECT (json_data->'position'->'lat') + 1.0 AS lat FROM updates LIMIT 5;
(+1.0 именно там, чтобы принудительно преобразовать в float. Мои актуальные запросы намного сложнее, этот запрос является всего лишь тестовым случаем для проблемы.)
Я получаю сообщение об ошибке:
ERROR: operator does not exist: jsonb + numeric
Если я добавляю в явное литье:
SELECT (json_data->'position'->'lat')::float + 1.0 AS lat FROM updates LIMIT 5;
ошибка становится:
ERROR: operator does not exist: jsonb + double precesion
Я понимаю, что большинство значений jsonb нельзя вставлять в float, но в этом случае я знаю, что lats - все JSON-номера.
Есть ли функция, которая переводит значения jsonb в float (или возвращает NULL для uncastable)?
Ответы
Ответ 1
Есть две операции для получения значения из JSON
. Первая ->
вернет JSON
. Второй ->>
будет возвращать текст.
Подробности: Функции и операторы JSON
Попробуйте
SELECT (json_data->'position'->>'lat')::float + 1.0 AS lat
FROM updates
LIMIT 5
Ответ 2
В документации есть также функции
jsonb_populate_record()
jsonb_populate_recordset()
Аналог их близнецов json (присутствует с pg 9.3)
json_populate_record()
json_populate_recordset()
Вам нужен предопределенный тип строки. Либо используйте тип строки существующей таблицы, либо укажите ее с помощью CREATE TYPE
. Или замените временную таблицу ad hoc:
CREATE TEMP TABLE x(lat float);
Может быть один столбец или длинный список столбцов.
Только те столбцы заполнены, где имя соответствует клавише в объекте json
. Значение принудительно применяется к столбцу type и должно быть совместимым или создается исключение. Другие ключи игнорируются.
SELECT lat + 1 -- no need for 1.0, this is float already
FROM updates u
, jsonb_populate_record(NULL::x, u.json_data->'position')
LIMIT 5;
Используя неявный LATERAL JOIN
здесь.
Аналогично, используйте jsonb_populate_recordset()
для разложения массивов на несколько строк для каждой записи.
Это работает аналогично в Postgres 9.3 с json
. Существует дополнительное преимущество, заключающееся в том, что литье в/из text
внутренне не требуется для числовых данных в jsonb
.
Ответ 3
AFAIK там нет json- > float casting в Postgres, поэтому вы можете попробовать явный (json_data->'position'->'lat')::text::float
cast
Ответ 4
Вы должны передать значение json в текст и затем плавать.
Попробуйте следующее:
(json_data #>> '{field}')::float