искать?
Можно в подзапросах в Join, можно в CTE. Но в общем -- лучшэ потренироваться на чём-нибудь простом, чтобы таких странных вопросов меньшэ было.
Например, принцыпиальная достаточно разница -- во что она "спарзена" и насколько она будет меняться в зависимости от кортэжа и другие подобные вопросы.
просто somevalue::json имел в виду засунуть в переменную, чтобы она не парсилась при каждом вызове. У всех кортеджей жсонки с одинаковой структурой
Можно ещё параметром сделать, кстати. Постгресовым, который нумерованный. Но тут ужэ многое зависит от клиентской библиотеки.
Кстати, если потом этот json применяется для наложения десятка фильтров, то лучше сразу отказаться от этой идеи. Если json небольшой, то разбираться будет быстро (при чём, при правильном подходе - ещё на этапе планирования). Но если его обернуть в cte, планировщик не увидит значений параметров и сформирует гарантированно плохой план.
Если разбираться будет immutable функцыей -- то ему, скорее всего, будет всё равно.
По крайней мере, на PostgreSQL 13, CTE приводит к невозможности получить правильные оценки селективности и, как следствие - использование неподходящего индекса. https://dbfiddle.uk/?rdbms=postgres_13&fiddle=9203d9b7910496658bf5579ff0d015cc
Но правильнее преобразование в CTE делается всё-таки как-то вот так: WITH myjson(v) AS ( select jsonb '{"a_min": 5, "a_max": 5, "b_min": 1, "b_max": 1000}' ) SELECT mytable.* FROM myjson CROSS JOIN mytable WHERE mytable.a BETWEEN CAST (myjson.v -> 'a_min' AS integer) AND CAST (myjson.v -> 'a_max' AS integer) AND mytable.b BETWEEN cast(myjson.v -> 'b_min' AS integer) AND CAST(myjson.v -> 'b_max' AS integer); А не так, как Вы показали, нет?
Хотя не, наврал. Можно найти рабочий вариант: explain analyze with myjson as not materialized (select cast(j ->> 'a_min' as integer) a_min, cast(j ->> 'a_max' as integer) a_max, cast(j ->> 'b_min' as integer) b_min, cast(j ->> 'b_max' as integer) b_max from (select jsonb '{"a_min": 5, "a_max": 5, "b_min": 1, "b_max": 1000}' j) j) select * from mytable join myjson on a between a_min and a_max and b between b_min and b_max; При чём, работает даже в 12й версии. Надо будет взять на вооружение.
Согласен (только мой вариант с кастами в cte всё-таки чуть проще). Только не согласен с вариантом доставания числа через cast(json_field -> 'key' as integer). Если вдруг в исходном json-е прилетит не тот тип, то получим ошибку... точнее, с integer не получим, а вот с boolean-ом получим. Пока такое разное поведение присутствует, лучше преобразовывать через строку.
> Если вдруг в исходном json-е прилетит не тот тип, то получим ошибку... Ну и прекрасно, IMHO. Мне как-то не нравится "заметать ошибки под ковёр". ;)
Еще раз перепроверил, с integer тоже падает. Тогда согласен, лучше так, но только cast jsonb -> integer появился только в PostgreSQL 11, т.е., не всем подойдёт. Впрочем, в 11 и подставляться значения из CTE тоже не будут.
вроде json хранится в тексте и всегда разбирается, в отличии от jsonb
Обсуждают сегодня