Постгреси 9.4 або новіші
Очевидно, надихнувшись цією публікацією , Postgres 9.4 додав відсутні функції:
Дякую Лоренсу Роу за патч та Ендрю Данстану за вчинення!
Щоб зняти масив JSON. Потім використовуйте array_agg()
або конструктор ARRAY, щоб створити з нього масив Postgres . Або string_agg()
побудувати text
рядок .
Об'єднайте немережі елементи на рядок у підзапросі LATERAL
чи кореляції. Тоді оригінальне замовлення зберігається і нам не потрібен ORDER BY
, GROUP BY
а то й унікальний ключ у зовнішньому запиті. Побачити:
Замініть "json" на "jsonb" на jsonb
всі наступні SQL-коди.
SELECT t.tbl_id, d.list
FROM tbl t
CROSS JOIN LATERAL (
SELECT string_agg(d.elem::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') AS d(elem)
) d;
Короткий синтаксис:
SELECT t.tbl_id, d.list
FROM tbl t, LATERAL (
SELECT string_agg(value::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') -- col name default: "value"
) d;
Пов'язані:
Конструктор ARRAY у корельованому підзапиті:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Пов'язані:
Тонка різниця : null
елементи зберігаються у фактичних масивах . Це неможливо для вищезазначених запитів, що створюють text
рядок, який не може містити null
значення. Точне уявлення є масивом.
Функціональна обгортка
Для багаторазового використання, щоб зробити це ще простіше, інкапсулюйте логіку у функції:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Зробіть це функцією SQL , щоб вона могла бути вписана в більші запити.
Зробіть це IMMUTABLE
(оскільки воно є), щоб уникнути повторного оцінювання у великих запитах і дозволити його в виразах індексу.
Виклик:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> скрипка тут
Постгреси 9.3 або новіші
Використовуйте функцію json_array_elements()
. Але ми отримуємо з нього подвійні цитовані рядки .
Альтернативний запит з агрегуванням у зовнішньому запиті. CROSS JOIN
видаляє рядки з відсутніми або порожніми масивами. Може бути корисним і для обробки елементів. Нам потрібен унікальний ключ для агрегації:
SELECT t.tbl_id, string_agg(d.elem::text, ', ') AS list
FROM tbl t
CROSS JOIN LATERAL json_array_elements(t.data->'tags') AS d(elem)
GROUP BY t.tbl_id;
ARRAY конструктор, як і раніше з цитованими рядками:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Зауважте, що null
перетворюється у текстове значення "null", на відміну від вище. Неправильно, строго кажучи, і потенційно неоднозначне.
Бідні чоловіки розмовляють з trim()
:
SELECT t.tbl_id, string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
GROUP BY 1;
Отримайте один рядок із tbl:
SELECT string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
WHERE t.tbl_id = 1;
Рядки утворюють корельований підзапит:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
Конструктор ARRAY:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Оригінальний (застарілий) скрипт SQL .
db <> скрипка тут.
Пов'язані:
Примітки (застарілі з р. 9.4)
Нам знадобиться a json_array_elements_text(json)
, близнюк, json_array_elements(json)
щоб повернути належні text
значення з масиву JSON. Але цього, здається, не вистачає з наданого арсеналу функцій JSON . Або якась інша функція для отримання text
значення зі скалярного JSON
значення. Мені, здається, і цього не вистачає.
Тож я імпровізував trim()
, але це не вдасться до нетривіальних випадків ...
json_extract_path_text(your_column, 'tags')
те, що ви шукаєте?