Постгреси 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')те, що ви шукаєте?